diff options
Diffstat (limited to 'src/plugins/python/pythonrunconfiguration.cpp')
-rw-r--r-- | src/plugins/python/pythonrunconfiguration.cpp | 98 |
1 files changed, 48 insertions, 50 deletions
diff --git a/src/plugins/python/pythonrunconfiguration.cpp b/src/plugins/python/pythonrunconfiguration.cpp index 1783b46930..4d9b12cdc8 100644 --- a/src/plugins/python/pythonrunconfiguration.cpp +++ b/src/plugins/python/pythonrunconfiguration.cpp @@ -60,10 +60,10 @@ using namespace Utils; namespace Python { namespace Internal { -class PythonOutputFormatter : public OutputFormatter +class PythonOutputLineParser : public OutputLineParser { public: - PythonOutputFormatter() + PythonOutputLineParser() // Note that moc dislikes raw string literals. : filePattern("^(\\s*)(File \"([^\"]+)\", line (\\d+), .*$)") { @@ -71,66 +71,64 @@ public: } private: - void appendMessage(const QString &text, OutputFormat format) final + Result handleLine(const QString &text, OutputFormat format) final { - const bool isTrace = (format == StdErrFormat - || format == StdErrFormatSameLine) - && (text.startsWith("Traceback (most recent call last):") - || text.startsWith("\nTraceback (most recent call last):")); - - if (!isTrace) { - OutputFormatter::appendMessage(text, format); - return; + if (!m_inTraceBack) { + m_inTraceBack = format == StdErrFormat + && text.startsWith("Traceback (most recent call last):"); + if (m_inTraceBack) + return Status::InProgress; + return Status::NotHandled; } - const QTextCharFormat frm = charFormat(format); - const Core::Id id(PythonErrorTaskCategory); - QVector<Task> tasks; - const QStringList lines = text.split('\n'); - unsigned taskId = unsigned(lines.size()); - - for (const QString &line : lines) { - const QRegularExpressionMatch match = filePattern.match(line); - if (match.hasMatch()) { - QTextCursor tc = plainTextEdit()->textCursor(); - tc.movePosition(QTextCursor::End, QTextCursor::MoveAnchor); - tc.insertText('\n' + match.captured(1)); - tc.insertText(match.captured(2), linkFormat(frm, match.captured(2))); - - const auto fileName = FilePath::fromString(match.captured(3)); - const int lineNumber = match.capturedRef(4).toInt(); - Task task(Task::Warning, - QString(), fileName, lineNumber, id); - task.taskId = --taskId; - tasks.append(task); + const Utils::Id category(PythonErrorTaskCategory); + const QRegularExpressionMatch match = filePattern.match(text); + if (match.hasMatch()) { + const LinkSpec link(match.capturedStart(2), match.capturedLength(2), match.captured(2)); + const auto fileName = FilePath::fromString(match.captured(3)); + const int lineNumber = match.captured(4).toInt(); + m_tasks.append({Task::Warning, QString(), fileName, lineNumber, category}); + return {Status::InProgress, {link}}; + } + + Status status = Status::InProgress; + if (text.startsWith(' ')) { + // Neither traceback start, nor file, nor error message line. + // Not sure if that can actually happen. + if (m_tasks.isEmpty()) { + m_tasks.append({Task::Warning, text.trimmed(), {}, -1, category}); } else { - if (!tasks.isEmpty()) { - Task &task = tasks.back(); - if (!task.description.isEmpty()) - task.description += ' '; - task.description += line.trimmed(); - } - OutputFormatter::appendMessage('\n' + line, format); + Task &task = m_tasks.back(); + if (!task.summary.isEmpty()) + task.summary += ' '; + task.summary += text.trimmed(); } - } - if (!tasks.isEmpty()) { - tasks.back().type = Task::Error; - for (auto rit = tasks.crbegin(), rend = tasks.crend(); rit != rend; ++rit) + } else { + // The actual exception. This ends the traceback. + TaskHub::addTask({Task::Error, text, {}, -1, category}); + for (auto rit = m_tasks.crbegin(), rend = m_tasks.crend(); rit != rend; ++rit) TaskHub::addTask(*rit); + m_tasks.clear(); + m_inTraceBack = false; + status = Status::Done; } + return status; } - void handleLink(const QString &href) final + bool handleLink(const QString &href) final { const QRegularExpressionMatch match = filePattern.match(href); if (!match.hasMatch()) - return; + return false; const QString fileName = match.captured(3); - const int lineNumber = match.capturedRef(4).toInt(); + const int lineNumber = match.captured(4).toInt(); Core::EditorManager::openEditorAt(fileName, lineNumber); + return true; } const QRegularExpression filePattern; + QList<Task> m_tasks; + bool m_inTraceBack; }; //////////////////////////////////////////////////////////////// @@ -235,7 +233,7 @@ public: MainScriptAspect() = default; }; -PythonRunConfiguration::PythonRunConfiguration(Target *target, Core::Id id) +PythonRunConfiguration::PythonRunConfiguration(Target *target, Utils::Id id) : RunConfiguration(target, id) { auto interpreterAspect = addAspect<InterpreterAspect>(); @@ -333,10 +331,10 @@ PythonRunConfigurationFactory::PythonRunConfigurationFactory() PythonOutputFormatterFactory::PythonOutputFormatterFactory() { - setFormatterCreator([](Target *t) -> OutputFormatter * { - if (t->project()->mimeType() == Constants::C_PY_MIMETYPE) - return new PythonOutputFormatter; - return nullptr; + setFormatterCreator([](Target *t) -> QList<OutputLineParser *> { + if (t && t->project()->mimeType() == Constants::C_PY_MIMETYPE) + return {new PythonOutputLineParser}; + return {}; }); } |