Debugger: use FilePath in stack frames

Change-Id: I98b6aa60e1b72be3482916446b87cee89e6cf2a4
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
David Schulz
2021-10-26 10:48:43 +02:00
parent 67607e4bc6
commit bc55c7cc70
12 changed files with 55 additions and 50 deletions

View File

@@ -1079,7 +1079,7 @@ void CdbEngine::activateFrame(int index)
if (debug || debugLocals) if (debug || debugLocals)
qDebug("activateFrame idx=%d '%s' %d", index, qDebug("activateFrame idx=%d '%s' %d", index,
qPrintable(frame.file), frame.line); qPrintable(frame.file.toUserOutput()), frame.line);
stackHandler()->setCurrentIndex(index); stackHandler()->setCurrentIndex(index);
gotoLocation(frame); gotoLocation(frame);
if (m_pythonVersion > 0x030000) if (m_pythonVersion > 0x030000)
@@ -2615,7 +2615,7 @@ static StackFrames parseFrames(const GdbMi &gdbmi, bool *incomplete = nullptr)
frame.level = QString::number(i); frame.level = QString::number(i);
const GdbMi fullName = frameMi["fullname"]; const GdbMi fullName = frameMi["fullname"];
if (fullName.isValid()) { if (fullName.isValid()) {
frame.file = Utils::FileUtils::normalizedPathName(fullName.data()); frame.file = Utils::FilePath::fromString(fullName.data()).normalizedPathName();
frame.line = frameMi["line"].data().toInt(); frame.line = frameMi["line"].data().toInt();
frame.usable = false; // To be decided after source path mapping. frame.usable = false; // To be decided after source path mapping.
const GdbMi languageMi = frameMi["language"]; const GdbMi languageMi = frameMi["language"];
@@ -2661,12 +2661,12 @@ unsigned CdbEngine::parseStackTrace(const GdbMi &data, bool sourceStepInto)
return ParseStackStepOut; return ParseStackStepOut;
} }
if (hasFile) { if (hasFile) {
const NormalizedSourceFileName fileName = sourceMapNormalizeFileNameFromDebugger(frames.at(i).file); const NormalizedSourceFileName fileName = sourceMapNormalizeFileNameFromDebugger(frames.at(i).file.toString());
if (!fileName.exists && i == 0 && sourceStepInto) { if (!fileName.exists && i == 0 && sourceStepInto) {
showMessage("Step into: Hit frame with no source, step out...", LogMisc); showMessage("Step into: Hit frame with no source, step out...", LogMisc);
return ParseStackStepOut; return ParseStackStepOut;
} }
frames[i].file = fileName.fileName; frames[i].file = FilePath::fromString(fileName.fileName);
frames[i].usable = fileName.exists; frames[i].usable = fileName.exists;
if (current == -1 && frames[i].usable) if (current == -1 && frames[i].usable)
current = i; current = i;

View File

@@ -161,7 +161,7 @@ static bool debuggerActionsEnabledHelper(DebuggerState state)
Location::Location(const StackFrame &frame, bool marker) Location::Location(const StackFrame &frame, bool marker)
{ {
m_fileName = Utils::FilePath::fromString(frame.file); m_fileName = frame.file;
m_lineNumber = frame.line; m_lineNumber = frame.line;
m_needsMarker = marker; m_needsMarker = marker;
m_functionName = frame.function; m_functionName = frame.function;

View File

@@ -718,10 +718,9 @@ DebuggerToolTipContext::DebuggerToolTipContext()
{ {
} }
static bool filesMatch(const QString &file1, const QString &file2) static bool filesMatch(const FilePath &file1, const FilePath &file2)
{ {
return FilePath::fromString(QFileInfo(file1).canonicalFilePath()) return file1.canonicalPath() == file2.canonicalPath();
== FilePath::fromString(QFileInfo(file2).canonicalFilePath());
} }
bool DebuggerToolTipContext::matchesFrame(const StackFrame &frame) const bool DebuggerToolTipContext::matchesFrame(const StackFrame &frame) const
@@ -945,7 +944,7 @@ void DebuggerToolTipHolder::saveSessionData(QXmlStreamWriter &w) const
w.writeStartElement(toolTipElementC); w.writeStartElement(toolTipElementC);
QXmlStreamAttributes attributes; QXmlStreamAttributes attributes;
// attributes.append(toolTipClassAttributeC, QString::fromLatin1(metaObject()->className())); // attributes.append(toolTipClassAttributeC, QString::fromLatin1(metaObject()->className()));
attributes.append(fileNameAttributeC, context.fileName); attributes.append(fileNameAttributeC, context.fileName.toString());
if (!context.function.isEmpty()) if (!context.function.isEmpty())
attributes.append(functionAttributeC, context.function); attributes.append(functionAttributeC, context.function);
attributes.append(textPositionAttributeC, QString::number(context.position)); attributes.append(textPositionAttributeC, QString::number(context.position));
@@ -1019,15 +1018,15 @@ void DebuggerToolTipManagerPrivate::updateVisibleToolTips()
return; return;
} }
const QString fileName = toolTipEditor->textDocument()->filePath().toString(); const FilePath filePath = toolTipEditor->textDocument()->filePath();
if (fileName.isEmpty()) { if (filePath.isEmpty()) {
hideAllToolTips(); hideAllToolTips();
return; return;
} }
// Reposition and show all tooltips of that file. // Reposition and show all tooltips of that file.
for (DebuggerToolTipHolder *tooltip : qAsConst(m_tooltips)) { for (DebuggerToolTipHolder *tooltip : qAsConst(m_tooltips)) {
if (tooltip->context.fileName == fileName) if (tooltip->context.fileName == filePath)
tooltip->positionShow(toolTipEditor->editorWidget()); tooltip->positionShow(toolTipEditor->editorWidget());
else else
tooltip->widget->hide(); tooltip->widget->hide();
@@ -1085,7 +1084,8 @@ void DebuggerToolTipManagerPrivate::loadSessionData()
if (readStartElement(r, toolTipElementC)) { if (readStartElement(r, toolTipElementC)) {
const QXmlStreamAttributes attributes = r.attributes(); const QXmlStreamAttributes attributes = r.attributes();
DebuggerToolTipContext context; DebuggerToolTipContext context;
context.fileName = attributes.value(fileNameAttributeC).toString(); context.fileName = FilePath::fromString(
attributes.value(fileNameAttributeC).toString());
context.position = attributes.value(textPositionAttributeC).toString().toInt(); context.position = attributes.value(textPositionAttributeC).toString().toInt();
context.line = attributes.value(textLineAttributeC).toString().toInt(); context.line = attributes.value(textLineAttributeC).toString().toInt();
context.column = attributes.value(textColumnAttributeC).toString().toInt(); context.column = attributes.value(textColumnAttributeC).toString().toInt();
@@ -1197,7 +1197,7 @@ void DebuggerToolTipManagerPrivate::slotTooltipOverrideRequested
DebuggerToolTipContext context; DebuggerToolTipContext context;
context.engineType = m_engine->objectName(); context.engineType = m_engine->objectName();
context.fileName = document->filePath().toString(); context.fileName = document->filePath();
context.position = pos; context.position = pos;
editorWidget->convertPosition(pos, &context.line, &context.column); editorWidget->convertPosition(pos, &context.line, &context.column);
QString raw = cppExpressionAt(editorWidget, context.position, &context.line, &context.column, QString raw = cppExpressionAt(editorWidget, context.position, &context.line, &context.column,

View File

@@ -27,6 +27,8 @@
#include "debuggerconstants.h" #include "debuggerconstants.h"
#include <utils/filepath.h>
#include <QCoreApplication> #include <QCoreApplication>
#include <QDate> #include <QDate>
#include <QPoint> #include <QPoint>
@@ -46,7 +48,7 @@ public:
bool isSame(const DebuggerToolTipContext &other) const; bool isSame(const DebuggerToolTipContext &other) const;
QString toolTip() const; QString toolTip() const;
QString fileName; Utils::FilePath fileName;
int position; int position;
int line; int line;
int column; int column;

View File

@@ -346,11 +346,11 @@ void PdbEngine::refreshState(const GdbMi &reportedState)
void PdbEngine::refreshLocation(const GdbMi &reportedLocation) void PdbEngine::refreshLocation(const GdbMi &reportedLocation)
{ {
StackFrame frame; StackFrame frame;
frame.file = reportedLocation["file"].data(); frame.file = Utils::FilePath::fromString(reportedLocation["file"].data());
frame.line = reportedLocation["line"].toInt(); frame.line = reportedLocation["line"].toInt();
frame.usable = QFileInfo(frame.file).isReadable(); frame.usable = frame.file.isReadableFile();
if (state() == InferiorRunOk) { if (state() == InferiorRunOk) {
showMessage(QString("STOPPED AT: %1:%2").arg(frame.file).arg(frame.line)); showMessage(QString("STOPPED AT: %1:%2").arg(frame.file.toUserOutput()).arg(frame.line));
gotoLocation(frame); gotoLocation(frame);
notifyInferiorSpontaneousStop(); notifyInferiorSpontaneousStop();
updateAll(); updateAll();
@@ -535,7 +535,7 @@ void PdbEngine::refreshStack(const GdbMi &stack)
for (const GdbMi &item : stack["frames"]) { for (const GdbMi &item : stack["frames"]) {
StackFrame frame; StackFrame frame;
frame.level = item["level"].data(); frame.level = item["level"].data();
frame.file = item["file"].data(); frame.file = Utils::FilePath::fromString(item["file"].data());
frame.function = item["function"].data(); frame.function = item["function"].data();
frame.module = item["function"].data(); frame.module = item["function"].data();
frame.line = item["line"].toInt(); frame.line = item["line"].toInt();
@@ -544,7 +544,7 @@ void PdbEngine::refreshStack(const GdbMi &stack)
if (usable.isValid()) if (usable.isValid())
frame.usable = usable.data().toInt(); frame.usable = usable.data().toInt();
else else
frame.usable = QFileInfo(frame.file).isReadable(); frame.usable = frame.file.isReadableFile();
frames.append(frame); frames.append(frame);
} }
bool canExpand = stack["hasmore"].toInt(); bool canExpand = stack["hasmore"].toInt();

View File

@@ -2036,8 +2036,9 @@ StackFrame QmlEnginePrivate::extractStackFrame(const QVariant &bodyVal)
stackFrame.function = extractString(body.value("func")); stackFrame.function = extractString(body.value("func"));
if (stackFrame.function.isEmpty()) if (stackFrame.function.isEmpty())
stackFrame.function = QCoreApplication::translate("QmlEngine", "Anonymous Function"); stackFrame.function = QCoreApplication::translate("QmlEngine", "Anonymous Function");
stackFrame.file = engine->toFileInProject(extractString(body.value("script"))); stackFrame.file = FilePath::fromString(
stackFrame.usable = QFileInfo(stackFrame.file).isReadable(); engine->toFileInProject(extractString(body.value("script"))));
stackFrame.usable = stackFrame.file.isReadableFile();
stackFrame.receiver = extractString(body.value("receiver")); stackFrame.receiver = extractString(body.value("receiver"));
stackFrame.line = body.value("line").toInt() + 1; stackFrame.line = body.value("line").toInt() + 1;

View File

@@ -134,7 +134,7 @@ void SourceAgent::updateLocationMarker()
d->editor->textDocument()->removeMark(d->locationMark); d->editor->textDocument()->removeMark(d->locationMark);
delete d->locationMark; delete d->locationMark;
d->locationMark = nullptr; d->locationMark = nullptr;
if (d->engine->stackHandler()->currentFrame().file == d->path) { if (d->engine->stackHandler()->currentFrame().file == Utils::FilePath::fromString(d->path)) {
int lineNumber = d->engine->stackHandler()->currentFrame().line; int lineNumber = d->engine->stackHandler()->currentFrame().line;
d->locationMark = new TextMark(Utils::FilePath(), lineNumber, d->locationMark = new TextMark(Utils::FilePath(), lineNumber,

View File

@@ -190,7 +190,7 @@ static void blockRecursion(const Overview &overview,
QStringList getUninitializedVariables(const Snapshot &snapshot, QStringList getUninitializedVariables(const Snapshot &snapshot,
const QString &functionName, const QString &functionName,
const QString &file, const FilePath &file,
int line) int line)
{ {
QStringList result; QStringList result;

View File

@@ -33,6 +33,7 @@ class TextDocument;
class TextEditorWidget; class TextEditorWidget;
} }
namespace Utils { class FilePath; }
namespace CPlusPlus { class Snapshot; } namespace CPlusPlus { class Snapshot; }
namespace Debugger { namespace Debugger {
@@ -52,7 +53,7 @@ QString cppFunctionAt(const QString &fileName, int line, int column = 0);
// of a function from the code model. Shadowed variables will // of a function from the code model. Shadowed variables will
// be reported using the debugger naming conventions '<shadowed n>' // be reported using the debugger naming conventions '<shadowed n>'
QStringList getUninitializedVariables(const CPlusPlus::Snapshot &snapshot, QStringList getUninitializedVariables(const CPlusPlus::Snapshot &snapshot,
const QString &function, const QString &file, int line); const QString &function, const Utils::FilePath &file, int line);
ContextData getLocationContext(TextEditor::TextDocument *document, int lineNumber); ContextData getLocationContext(TextEditor::TextDocument *document, int lineNumber);

View File

@@ -35,6 +35,8 @@
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
using namespace Utils;
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
@@ -93,7 +95,7 @@ StackFrame StackFrame::parseFrame(const GdbMi &frameMi, const DebuggerRunParamet
frame.level = frameMi["level"].data(); frame.level = frameMi["level"].data();
frame.function = frameMi["function"].data(); frame.function = frameMi["function"].data();
frame.module = frameMi["module"].data(); frame.module = frameMi["module"].data();
frame.file = frameMi["file"].data(); frame.file = FilePath::fromString(frameMi["file"].data());
frame.line = frameMi["line"].toInt(); frame.line = frameMi["line"].toInt();
frame.address = frameMi["address"].toAddress(); frame.address = frameMi["address"].toAddress();
frame.context = frameMi["context"].data(); frame.context = frameMi["context"].data();
@@ -107,13 +109,13 @@ StackFrame StackFrame::parseFrame(const GdbMi &frameMi, const DebuggerRunParamet
if (usable.isValid()) if (usable.isValid())
frame.usable = usable.data().toInt(); frame.usable = usable.data().toInt();
else else
frame.usable = QFileInfo(frame.file).isReadable(); frame.usable = frame.file.isReadableFile();
return frame; return frame;
} }
QString StackFrame::toToolTip() const QString StackFrame::toToolTip() const
{ {
const QString filePath = QDir::toNativeSeparators(file); const QString filePath = file.toUserOutput();
QString res; QString res;
QTextStream str(&res); QTextStream str(&res);
str << "<html><body><table>"; str << "<html><body><table>";
@@ -150,7 +152,7 @@ QString StackFrame::toToolTip() const
"frame. However, matching sources have not been found."); "frame. However, matching sources have not been found.");
showDistributionNote = true; showDistributionNote = true;
} }
if (!Utils::HostOsInfo::isWindowsHost() && showDistributionNote) { if (!HostOsInfo::isWindowsHost() && showDistributionNote) {
str << ' ' << tr("Note that most distributions ship debug information " str << ' ' << tr("Note that most distributions ship debug information "
"in separate packages."); "in separate packages.");
} }
@@ -159,19 +161,14 @@ QString StackFrame::toToolTip() const
return res; return res;
} }
static QString findFile(const QString &baseDir, const QString &relativeFile) static FilePath findFile(const FilePath &baseDir, const FilePath &relativeFile)
{ {
QDir dir(baseDir); for (FilePath dir(baseDir); !dir.isEmpty(); dir = dir.parentDir()) {
while (true) { const FilePath absolutePath = dir.resolvePath(relativeFile);
const QString path = dir.absoluteFilePath(relativeFile); if (absolutePath.isFile())
const QFileInfo fi(path); return absolutePath;
if (fi.isFile())
return path;
if (dir.isRoot())
break;
dir.cdUp();
} }
return QString(); return {};
} }
// Try to resolve files coming from resource files. // Try to resolve files coming from resource files.
@@ -179,21 +176,23 @@ void StackFrame::fixQrcFrame(const DebuggerRunParameters &rp)
{ {
if (language != QmlLanguage) if (language != QmlLanguage)
return; return;
QFileInfo aFi(file); if (file.isAbsolutePath()) {
if (aFi.isAbsolute()) { usable = file.isFile();
usable = aFi.isFile();
return; return;
} }
if (!file.startsWith("qrc:/")) if (!file.startsWith("qrc:/"))
return; return;
QString relativeFile = file.right(file.size() - 5); FilePath relativeFile = file;
while (relativeFile.startsWith('/')) QString relativePath = file.path();
relativeFile = relativeFile.mid(1); relativePath = relativePath.right(relativePath.size() - 5);
while (relativePath.startsWith('/'))
relativePath = relativePath.mid(1);
relativeFile.setPath(relativePath);
QString absFile = findFile(rp.projectSourceDirectory.toString(), relativeFile); FilePath absFile = findFile(rp.projectSourceDirectory, relativeFile);
if (absFile.isEmpty()) if (absFile.isEmpty())
absFile = findFile(QDir::currentPath(), relativeFile); absFile = findFile(FilePath::fromString(QDir::currentPath()), relativeFile);
if (absFile.isEmpty()) if (absFile.isEmpty())
return; return;

View File

@@ -27,6 +27,8 @@
#include "debuggerconstants.h" #include "debuggerconstants.h"
#include <utils/filepath.h>
#include <QCoreApplication> #include <QCoreApplication>
#include <QMetaType> #include <QMetaType>
@@ -56,7 +58,7 @@ public:
DebuggerLanguage language = CppLanguage; DebuggerLanguage language = CppLanguage;
QString level; QString level;
QString function; QString function;
QString file; // We try to put an absolute file name in there. Utils::FilePath file;// We try to put an absolute file name in there.
QString module; // Sometimes something like "/usr/lib/libstdc++.so.6" QString module; // Sometimes something like "/usr/lib/libstdc++.so.6"
QString receiver; // Used in ScriptEngine only. QString receiver; // Used in ScriptEngine only.
qint32 line = -1; qint32 line = -1;

View File

@@ -101,7 +101,7 @@ QVariant StackFrameItem::data(int column, int role) const
case StackFunctionNameColumn: case StackFunctionNameColumn:
return simplifyType(frame.function); return simplifyType(frame.function);
case StackFileNameColumn: case StackFileNameColumn:
return frame.file.isEmpty() ? frame.module : FilePath::fromString(frame.file).fileName(); return frame.file.isEmpty() ? frame.module : frame.file.fileName();
case StackLineNumberColumn: case StackLineNumberColumn:
return frame.line > 0 ? QVariant(frame.line) : QVariant(); return frame.line > 0 ? QVariant(frame.line) : QVariant();
case StackAddressColumn: case StackAddressColumn: