From bc55c7cc70297c993e47c245d6ca4604670cec64 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Tue, 26 Oct 2021 10:48:43 +0200 Subject: [PATCH] Debugger: use FilePath in stack frames Change-Id: I98b6aa60e1b72be3482916446b87cee89e6cf2a4 Reviewed-by: hjk --- src/plugins/debugger/cdb/cdbengine.cpp | 8 ++-- src/plugins/debugger/debuggerengine.cpp | 2 +- .../debugger/debuggertooltipmanager.cpp | 18 ++++---- src/plugins/debugger/debuggertooltipmanager.h | 4 +- src/plugins/debugger/pdb/pdbengine.cpp | 10 ++--- src/plugins/debugger/qml/qmlengine.cpp | 5 ++- src/plugins/debugger/sourceagent.cpp | 2 +- src/plugins/debugger/sourceutils.cpp | 2 +- src/plugins/debugger/sourceutils.h | 3 +- src/plugins/debugger/stackframe.cpp | 45 +++++++++---------- src/plugins/debugger/stackframe.h | 4 +- src/plugins/debugger/stackhandler.cpp | 2 +- 12 files changed, 55 insertions(+), 50 deletions(-) diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index 58d0ef0b050..e1c8be48c31 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -1079,7 +1079,7 @@ void CdbEngine::activateFrame(int index) if (debug || debugLocals) qDebug("activateFrame idx=%d '%s' %d", index, - qPrintable(frame.file), frame.line); + qPrintable(frame.file.toUserOutput()), frame.line); stackHandler()->setCurrentIndex(index); gotoLocation(frame); if (m_pythonVersion > 0x030000) @@ -2615,7 +2615,7 @@ static StackFrames parseFrames(const GdbMi &gdbmi, bool *incomplete = nullptr) frame.level = QString::number(i); const GdbMi fullName = frameMi["fullname"]; 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.usable = false; // To be decided after source path mapping. const GdbMi languageMi = frameMi["language"]; @@ -2661,12 +2661,12 @@ unsigned CdbEngine::parseStackTrace(const GdbMi &data, bool sourceStepInto) return ParseStackStepOut; } 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) { showMessage("Step into: Hit frame with no source, step out...", LogMisc); return ParseStackStepOut; } - frames[i].file = fileName.fileName; + frames[i].file = FilePath::fromString(fileName.fileName); frames[i].usable = fileName.exists; if (current == -1 && frames[i].usable) current = i; diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index f2dd9f09a00..f2441aff33a 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -161,7 +161,7 @@ static bool debuggerActionsEnabledHelper(DebuggerState state) Location::Location(const StackFrame &frame, bool marker) { - m_fileName = Utils::FilePath::fromString(frame.file); + m_fileName = frame.file; m_lineNumber = frame.line; m_needsMarker = marker; m_functionName = frame.function; diff --git a/src/plugins/debugger/debuggertooltipmanager.cpp b/src/plugins/debugger/debuggertooltipmanager.cpp index efda99b07fa..814b71ecfb3 100644 --- a/src/plugins/debugger/debuggertooltipmanager.cpp +++ b/src/plugins/debugger/debuggertooltipmanager.cpp @@ -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()) - == FilePath::fromString(QFileInfo(file2).canonicalFilePath()); + return file1.canonicalPath() == file2.canonicalPath(); } bool DebuggerToolTipContext::matchesFrame(const StackFrame &frame) const @@ -945,7 +944,7 @@ void DebuggerToolTipHolder::saveSessionData(QXmlStreamWriter &w) const w.writeStartElement(toolTipElementC); QXmlStreamAttributes attributes; // attributes.append(toolTipClassAttributeC, QString::fromLatin1(metaObject()->className())); - attributes.append(fileNameAttributeC, context.fileName); + attributes.append(fileNameAttributeC, context.fileName.toString()); if (!context.function.isEmpty()) attributes.append(functionAttributeC, context.function); attributes.append(textPositionAttributeC, QString::number(context.position)); @@ -1019,15 +1018,15 @@ void DebuggerToolTipManagerPrivate::updateVisibleToolTips() return; } - const QString fileName = toolTipEditor->textDocument()->filePath().toString(); - if (fileName.isEmpty()) { + const FilePath filePath = toolTipEditor->textDocument()->filePath(); + if (filePath.isEmpty()) { hideAllToolTips(); return; } // Reposition and show all tooltips of that file. for (DebuggerToolTipHolder *tooltip : qAsConst(m_tooltips)) { - if (tooltip->context.fileName == fileName) + if (tooltip->context.fileName == filePath) tooltip->positionShow(toolTipEditor->editorWidget()); else tooltip->widget->hide(); @@ -1085,7 +1084,8 @@ void DebuggerToolTipManagerPrivate::loadSessionData() if (readStartElement(r, toolTipElementC)) { const QXmlStreamAttributes attributes = r.attributes(); DebuggerToolTipContext context; - context.fileName = attributes.value(fileNameAttributeC).toString(); + context.fileName = FilePath::fromString( + attributes.value(fileNameAttributeC).toString()); context.position = attributes.value(textPositionAttributeC).toString().toInt(); context.line = attributes.value(textLineAttributeC).toString().toInt(); context.column = attributes.value(textColumnAttributeC).toString().toInt(); @@ -1197,7 +1197,7 @@ void DebuggerToolTipManagerPrivate::slotTooltipOverrideRequested DebuggerToolTipContext context; context.engineType = m_engine->objectName(); - context.fileName = document->filePath().toString(); + context.fileName = document->filePath(); context.position = pos; editorWidget->convertPosition(pos, &context.line, &context.column); QString raw = cppExpressionAt(editorWidget, context.position, &context.line, &context.column, diff --git a/src/plugins/debugger/debuggertooltipmanager.h b/src/plugins/debugger/debuggertooltipmanager.h index 251addefbef..2c6853fcb60 100644 --- a/src/plugins/debugger/debuggertooltipmanager.h +++ b/src/plugins/debugger/debuggertooltipmanager.h @@ -27,6 +27,8 @@ #include "debuggerconstants.h" +#include + #include #include #include @@ -46,7 +48,7 @@ public: bool isSame(const DebuggerToolTipContext &other) const; QString toolTip() const; - QString fileName; + Utils::FilePath fileName; int position; int line; int column; diff --git a/src/plugins/debugger/pdb/pdbengine.cpp b/src/plugins/debugger/pdb/pdbengine.cpp index 620c37fb313..57f3383942d 100644 --- a/src/plugins/debugger/pdb/pdbengine.cpp +++ b/src/plugins/debugger/pdb/pdbengine.cpp @@ -346,11 +346,11 @@ void PdbEngine::refreshState(const GdbMi &reportedState) void PdbEngine::refreshLocation(const GdbMi &reportedLocation) { StackFrame frame; - frame.file = reportedLocation["file"].data(); + frame.file = Utils::FilePath::fromString(reportedLocation["file"].data()); frame.line = reportedLocation["line"].toInt(); - frame.usable = QFileInfo(frame.file).isReadable(); + frame.usable = frame.file.isReadableFile(); 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); notifyInferiorSpontaneousStop(); updateAll(); @@ -535,7 +535,7 @@ void PdbEngine::refreshStack(const GdbMi &stack) for (const GdbMi &item : stack["frames"]) { StackFrame frame; frame.level = item["level"].data(); - frame.file = item["file"].data(); + frame.file = Utils::FilePath::fromString(item["file"].data()); frame.function = item["function"].data(); frame.module = item["function"].data(); frame.line = item["line"].toInt(); @@ -544,7 +544,7 @@ void PdbEngine::refreshStack(const GdbMi &stack) if (usable.isValid()) frame.usable = usable.data().toInt(); else - frame.usable = QFileInfo(frame.file).isReadable(); + frame.usable = frame.file.isReadableFile(); frames.append(frame); } bool canExpand = stack["hasmore"].toInt(); diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index 416e1693bd1..b071ca6eb1b 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -2036,8 +2036,9 @@ StackFrame QmlEnginePrivate::extractStackFrame(const QVariant &bodyVal) stackFrame.function = extractString(body.value("func")); if (stackFrame.function.isEmpty()) stackFrame.function = QCoreApplication::translate("QmlEngine", "Anonymous Function"); - stackFrame.file = engine->toFileInProject(extractString(body.value("script"))); - stackFrame.usable = QFileInfo(stackFrame.file).isReadable(); + stackFrame.file = FilePath::fromString( + engine->toFileInProject(extractString(body.value("script")))); + stackFrame.usable = stackFrame.file.isReadableFile(); stackFrame.receiver = extractString(body.value("receiver")); stackFrame.line = body.value("line").toInt() + 1; diff --git a/src/plugins/debugger/sourceagent.cpp b/src/plugins/debugger/sourceagent.cpp index 7c1946e8121..02bddf6bfa3 100644 --- a/src/plugins/debugger/sourceagent.cpp +++ b/src/plugins/debugger/sourceagent.cpp @@ -134,7 +134,7 @@ void SourceAgent::updateLocationMarker() d->editor->textDocument()->removeMark(d->locationMark); delete d->locationMark; 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; d->locationMark = new TextMark(Utils::FilePath(), lineNumber, diff --git a/src/plugins/debugger/sourceutils.cpp b/src/plugins/debugger/sourceutils.cpp index 5b0b63cbff7..79850bdc420 100644 --- a/src/plugins/debugger/sourceutils.cpp +++ b/src/plugins/debugger/sourceutils.cpp @@ -190,7 +190,7 @@ static void blockRecursion(const Overview &overview, QStringList getUninitializedVariables(const Snapshot &snapshot, const QString &functionName, - const QString &file, + const FilePath &file, int line) { QStringList result; diff --git a/src/plugins/debugger/sourceutils.h b/src/plugins/debugger/sourceutils.h index 634fa662037..0487c354352 100644 --- a/src/plugins/debugger/sourceutils.h +++ b/src/plugins/debugger/sourceutils.h @@ -33,6 +33,7 @@ class TextDocument; class TextEditorWidget; } +namespace Utils { class FilePath; } namespace CPlusPlus { class Snapshot; } 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 // be reported using the debugger naming conventions '' 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); diff --git a/src/plugins/debugger/stackframe.cpp b/src/plugins/debugger/stackframe.cpp index d5a52bc4c38..1eea267f255 100644 --- a/src/plugins/debugger/stackframe.cpp +++ b/src/plugins/debugger/stackframe.cpp @@ -35,6 +35,8 @@ #include +using namespace Utils; + namespace Debugger { namespace Internal { @@ -93,7 +95,7 @@ StackFrame StackFrame::parseFrame(const GdbMi &frameMi, const DebuggerRunParamet frame.level = frameMi["level"].data(); frame.function = frameMi["function"].data(); frame.module = frameMi["module"].data(); - frame.file = frameMi["file"].data(); + frame.file = FilePath::fromString(frameMi["file"].data()); frame.line = frameMi["line"].toInt(); frame.address = frameMi["address"].toAddress(); frame.context = frameMi["context"].data(); @@ -107,13 +109,13 @@ StackFrame StackFrame::parseFrame(const GdbMi &frameMi, const DebuggerRunParamet if (usable.isValid()) frame.usable = usable.data().toInt(); else - frame.usable = QFileInfo(frame.file).isReadable(); + frame.usable = frame.file.isReadableFile(); return frame; } QString StackFrame::toToolTip() const { - const QString filePath = QDir::toNativeSeparators(file); + const QString filePath = file.toUserOutput(); QString res; QTextStream str(&res); str << ""; @@ -150,7 +152,7 @@ QString StackFrame::toToolTip() const "frame. However, matching sources have not been found."); showDistributionNote = true; } - if (!Utils::HostOsInfo::isWindowsHost() && showDistributionNote) { + if (!HostOsInfo::isWindowsHost() && showDistributionNote) { str << ' ' << tr("Note that most distributions ship debug information " "in separate packages."); } @@ -159,19 +161,14 @@ QString StackFrame::toToolTip() const return res; } -static QString findFile(const QString &baseDir, const QString &relativeFile) +static FilePath findFile(const FilePath &baseDir, const FilePath &relativeFile) { - QDir dir(baseDir); - while (true) { - const QString path = dir.absoluteFilePath(relativeFile); - const QFileInfo fi(path); - if (fi.isFile()) - return path; - if (dir.isRoot()) - break; - dir.cdUp(); + for (FilePath dir(baseDir); !dir.isEmpty(); dir = dir.parentDir()) { + const FilePath absolutePath = dir.resolvePath(relativeFile); + if (absolutePath.isFile()) + return absolutePath; } - return QString(); + return {}; } // Try to resolve files coming from resource files. @@ -179,21 +176,23 @@ void StackFrame::fixQrcFrame(const DebuggerRunParameters &rp) { if (language != QmlLanguage) return; - QFileInfo aFi(file); - if (aFi.isAbsolute()) { - usable = aFi.isFile(); + if (file.isAbsolutePath()) { + usable = file.isFile(); return; } if (!file.startsWith("qrc:/")) return; - QString relativeFile = file.right(file.size() - 5); - while (relativeFile.startsWith('/')) - relativeFile = relativeFile.mid(1); + FilePath relativeFile = file; + QString relativePath = file.path(); + 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()) - absFile = findFile(QDir::currentPath(), relativeFile); + absFile = findFile(FilePath::fromString(QDir::currentPath()), relativeFile); if (absFile.isEmpty()) return; diff --git a/src/plugins/debugger/stackframe.h b/src/plugins/debugger/stackframe.h index e51736b5184..9fd83a15e78 100644 --- a/src/plugins/debugger/stackframe.h +++ b/src/plugins/debugger/stackframe.h @@ -27,6 +27,8 @@ #include "debuggerconstants.h" +#include + #include #include @@ -56,7 +58,7 @@ public: DebuggerLanguage language = CppLanguage; QString level; 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 receiver; // Used in ScriptEngine only. qint32 line = -1; diff --git a/src/plugins/debugger/stackhandler.cpp b/src/plugins/debugger/stackhandler.cpp index a81433b99ee..488c6649b10 100644 --- a/src/plugins/debugger/stackhandler.cpp +++ b/src/plugins/debugger/stackhandler.cpp @@ -101,7 +101,7 @@ QVariant StackFrameItem::data(int column, int role) const case StackFunctionNameColumn: return simplifyType(frame.function); case StackFileNameColumn: - return frame.file.isEmpty() ? frame.module : FilePath::fromString(frame.file).fileName(); + return frame.file.isEmpty() ? frame.module : frame.file.fileName(); case StackLineNumberColumn: return frame.line > 0 ? QVariant(frame.line) : QVariant(); case StackAddressColumn: