aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@qt.io>2019-02-25 17:45:39 +0100
committerChristian Kandeler <christian.kandeler@qt.io>2019-03-04 09:52:13 +0000
commitd0db212575909ca18244bdfc99b952dffcd0e902 (patch)
treef0fbfb40bc34b20a5f4539b6936c8854e78433ee
parentb0e125ac11b1ad80717366a1270412d6b6b1be41 (diff)
Resolve ambiguous results of searches for relative file paths
Qt Creator extracts file names from the output of external processes in various places, for instance from compilers during the build. It often happens that such file names are not absolute, so they cannot be directly opened in an editor when the user clicks on their representation in some widget. That's why they are processed by the FileInProjectFinder facility first. This patch enhances the FileInProjectFinder to be able to return more than one candidate for a relative file path, and allows the user to choose between these candidates where possible. This way, we won't open a random file anymore when a project contains more than one file with the same name. Fixes: QTCREATORBUG-13623 Change-Id: Id19c9eace3e6b3dbde89f6528e6d02b55872d747 Reviewed-by: hjk <hjk@qt.io>
-rw-r--r--src/libs/utils/fileinprojectfinder.cpp137
-rw-r--r--src/libs/utils/fileinprojectfinder.h14
-rw-r--r--src/plugins/debugger/console/consoleview.cpp3
-rw-r--r--src/plugins/debugger/debuggerengine.cpp2
-rw-r--r--src/plugins/perfprofiler/perfprofilertool.cpp2
-rw-r--r--src/plugins/projectexplorer/fileinsessionfinder.cpp9
-rw-r--r--src/plugins/projectexplorer/fileinsessionfinder.h4
-rw-r--r--src/plugins/projectexplorer/task.cpp9
-rw-r--r--src/plugins/projectexplorer/task.h1
-rw-r--r--src/plugins/projectexplorer/taskmodel.cpp8
-rw-r--r--src/plugins/projectexplorer/taskwindow.cpp10
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerdetailsrewriter.cpp2
-rw-r--r--src/plugins/qtsupport/qtoutputformatter.cpp11
13 files changed, 133 insertions, 79 deletions
diff --git a/src/libs/utils/fileinprojectfinder.cpp b/src/libs/utils/fileinprojectfinder.cpp
index 0449589392..054e5d9c3b 100644
--- a/src/libs/utils/fileinprojectfinder.cpp
+++ b/src/libs/utils/fileinprojectfinder.cpp
@@ -31,11 +31,13 @@
#include "qrcparser.h"
#include "qtcassert.h"
+#include <QCursor>
#include <QDebug>
+#include <QDir>
#include <QFileInfo>
#include <QLoggingCategory>
+#include <QMenu>
#include <QUrl>
-#include <QDir>
#include <algorithm>
@@ -140,12 +142,12 @@ void FileInProjectFinder::addMappedPath(const FileName &localFilePath, const QSt
folder specified. Third, we walk the list of project files, and search for a file name match
there. If all fails, it returns the original path from the file URL.
*/
-QString FileInProjectFinder::findFile(const QUrl &fileUrl, bool *success) const
+FileNameList FileInProjectFinder::findFile(const QUrl &fileUrl, bool *success) const
{
qCDebug(finderLog) << "FileInProjectFinder: trying to find file" << fileUrl.toString() << "...";
if (fileUrl.scheme() == "qrc" || fileUrl.toString().startsWith(':')) {
- const QString result = m_qrcUrlFinder.find(fileUrl);
+ const FileNameList result = m_qrcUrlFinder.find(fileUrl);
if (!result.isEmpty()) {
if (success)
*success = true;
@@ -157,10 +159,12 @@ QString FileInProjectFinder::findFile(const QUrl &fileUrl, bool *success) const
if (originalPath.isEmpty()) // e.g. qrc://
originalPath = fileUrl.path();
- QString result = originalPath;
+ FileNameList result;
bool found = findFileOrDirectory(originalPath, [&](const QString &fileName, int) {
- result = fileName;
+ result << FileName::fromString(fileName);
});
+ if (!found)
+ result << FileName::fromString(originalPath);
if (success)
*success = found;
@@ -168,12 +172,12 @@ QString FileInProjectFinder::findFile(const QUrl &fileUrl, bool *success) const
return result;
}
-bool FileInProjectFinder::handleSuccess(const QString &originalPath, const QString &found,
+bool FileInProjectFinder::handleSuccess(const QString &originalPath, const QStringList &found,
int matchLength, const char *where) const
{
qCDebug(finderLog) << "FileInProjectFinder: found" << found << where;
CacheEntry entry;
- entry.path = found;
+ entry.paths = found;
entry.matchLength = matchLength;
m_cache.insert(originalPath, entry);
return true;
@@ -202,8 +206,10 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH
if (node) {
if (!node->localPath.isEmpty()) {
const QString localPath = node->localPath.toString();
- if (checkPath(localPath, origLength, fileHandler, directoryHandler))
- return handleSuccess(originalPath, localPath, origLength, "in mapped paths");
+ if (checkPath(localPath, origLength, fileHandler, directoryHandler)) {
+ return handleSuccess(originalPath, QStringList(localPath), origLength,
+ "in mapped paths");
+ }
} else if (directoryHandler) {
directoryHandler(node->children.keys(), origLength);
qCDebug(finderLog) << "FileInProjectFinder: found virtual directory" << originalPath
@@ -216,13 +222,18 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH
if (it != m_cache.end()) {
qCDebug(finderLog) << "FileInProjectFinder: checking cache ...";
// check if cached path is still there
- const CacheEntry &candidate = it.value();
- if (checkPath(candidate.path, candidate.matchLength, fileHandler, directoryHandler)) {
- qCDebug(finderLog) << "FileInProjectFinder: found" << candidate.path << "in the cache";
- return true;
- } else {
- m_cache.erase(it);
+ CacheEntry &candidate = it.value();
+ for (auto pathIt = candidate.paths.begin(); pathIt != candidate.paths.end();) {
+ if (checkPath(*pathIt, candidate.matchLength, fileHandler, directoryHandler)) {
+ qCDebug(finderLog) << "FileInProjectFinder: found" << *pathIt << "in the cache";
+ ++pathIt;
+ } else {
+ pathIt = candidate.paths.erase(pathIt);
+ }
}
+ if (!candidate.paths.empty())
+ return true;
+ m_cache.erase(it);
}
if (!m_projectDir.isEmpty()) {
@@ -244,7 +255,7 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH
if (prefixToIgnore == -1
&& checkPath(originalPath, origLength, fileHandler, directoryHandler)) {
- return handleSuccess(originalPath, originalPath, origLength,
+ return handleSuccess(originalPath, QStringList(originalPath), origLength,
"in project directory");
}
}
@@ -267,8 +278,11 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH
candidate.remove(0, prefixToIgnore);
candidate.prepend(m_projectDir.toString());
const int matchLength = origLength - prefixToIgnore;
- if (checkPath(candidate, matchLength, fileHandler, directoryHandler))
- return handleSuccess(originalPath, candidate, matchLength, "in project directory");
+ // FIXME: This might be a worse match than what we find later.
+ if (checkPath(candidate, matchLength, fileHandler, directoryHandler)) {
+ return handleSuccess(originalPath, QStringList(candidate), matchLength,
+ "in project directory");
+ }
prefixToIgnore = originalPath.indexOf(separator, prefixToIgnore + 1);
}
}
@@ -282,17 +296,23 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH
matches.append(filesWithSameFileName(lastSegment));
if (directoryHandler)
matches.append(pathSegmentsWithSameName(lastSegment));
- const QString matchedFilePath = bestMatch(matches, originalPath);
- const int matchLength = commonPostFixLength(matchedFilePath, originalPath);
- if (!matchedFilePath.isEmpty()
- && checkPath(matchedFilePath, matchLength, fileHandler, directoryHandler)) {
- return handleSuccess(originalPath, matchedFilePath, matchLength,
- "when matching project files");
+ const QStringList matchedFilePaths = bestMatches(matches, originalPath);
+ if (!matchedFilePaths.empty()) {
+ const int matchLength = commonPostFixLength(matchedFilePaths.first(), originalPath);
+ QStringList hits;
+ for (const QString &matchedFilePath : matchedFilePaths) {
+ if (checkPath(matchedFilePath, matchLength, fileHandler, directoryHandler))
+ hits << matchedFilePath;
+ }
+ if (!hits.empty())
+ return handleSuccess(originalPath, hits, matchLength, "when matching project files");
}
CacheEntry foundPath = findInSearchPaths(originalPath, fileHandler, directoryHandler);
- if (!foundPath.path.isEmpty())
- return handleSuccess(originalPath, foundPath.path, foundPath.matchLength, "in search path");
+ if (!foundPath.paths.isEmpty()) {
+ return handleSuccess(originalPath, foundPath.paths, foundPath.matchLength,
+ "in search path");
+ }
qCDebug(finderLog) << "FileInProjectFinder: checking absolute path in sysroot ...";
@@ -300,8 +320,10 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH
if (!m_sysroot.isEmpty()) {
FileName sysrootPath = m_sysroot;
sysrootPath.appendPath(originalPath);
- if (checkPath(sysrootPath.toString(), origLength, fileHandler, directoryHandler))
- return handleSuccess(originalPath, sysrootPath.toString(), origLength, "in sysroot");
+ if (checkPath(sysrootPath.toString(), origLength, fileHandler, directoryHandler)) {
+ return handleSuccess(originalPath, QStringList(sysrootPath.toString()), origLength,
+ "in sysroot");
+ }
}
qCDebug(finderLog) << "FileInProjectFinder: couldn't find file!";
@@ -315,7 +337,7 @@ FileInProjectFinder::CacheEntry FileInProjectFinder::findInSearchPaths(
for (const FileName &dirPath : m_searchDirectories) {
const CacheEntry found = findInSearchPath(dirPath.toString(), filePath,
fileHandler, directoryHandler);
- if (!found.path.isEmpty())
+ if (!found.paths.isEmpty())
return found;
}
@@ -340,17 +362,17 @@ FileInProjectFinder::CacheEntry FileInProjectFinder::findInSearchPath(
QString s = filePath;
while (!s.isEmpty()) {
CacheEntry result;
- result.path = searchPath + QLatin1Char('/') + s;
+ result.paths << searchPath + '/' + s;
result.matchLength = s.length() + 1;
- qCDebug(finderLog) << "FileInProjectFinder: trying" << result.path;
+ qCDebug(finderLog) << "FileInProjectFinder: trying" << result.paths.first();
- if (checkPath(result.path, result.matchLength, fileHandler, directoryHandler))
+ if (checkPath(result.paths.first(), result.matchLength, fileHandler, directoryHandler))
return result;
QString next = chopFirstDir(s);
if (next.isEmpty()) {
if (directoryHandler && QFileInfo(searchPath).fileName() == s) {
- result.path = searchPath;
+ result.paths = QStringList{searchPath};
directoryHandler(QDir(searchPath).entryList(), result.matchLength);
return result;
}
@@ -399,24 +421,30 @@ int FileInProjectFinder::commonPostFixLength(const QString &candidatePath,
return rank;
}
-QString FileInProjectFinder::bestMatch(const QStringList &filePaths, const QString &filePathToFind)
+QStringList FileInProjectFinder::bestMatches(const QStringList &filePaths,
+ const QString &filePathToFind)
{
if (filePaths.isEmpty())
- return QString();
+ return {};
if (filePaths.length() == 1) {
qCDebug(finderLog) << "FileInProjectFinder: found" << filePaths.first()
<< "in project files";
- return filePaths.first();
+ return filePaths;
}
- auto it = std::max_element(filePaths.constBegin(), filePaths.constEnd(),
- [&filePathToFind] (const QString &a, const QString &b) -> bool {
- return commonPostFixLength(a, filePathToFind) < commonPostFixLength(b, filePathToFind);
- });
- if (it != filePaths.cend()) {
- qCDebug(finderLog) << "FileInProjectFinder: found best match" << *it << "in project files";
- return *it;
+ int bestRank = -1;
+ QStringList bestFilePaths;
+ for (const QString &fp : filePaths) {
+ const int currentRank = commonPostFixLength(fp, filePathToFind);
+ if (currentRank < bestRank)
+ continue;
+ if (currentRank > bestRank) {
+ bestRank = currentRank;
+ bestFilePaths.clear();
+ }
+ bestFilePaths << fp;
}
- return QString();
+ QTC_CHECK(!bestFilePaths.empty());
+ return bestFilePaths;
}
FileNameList FileInProjectFinder::searchDirectories() const
@@ -434,9 +462,9 @@ FileInProjectFinder::PathMappingNode::~PathMappingNode()
qDeleteAll(children);
}
-QString FileInProjectFinder::QrcUrlFinder::find(const QUrl &fileUrl) const
+FileNameList FileInProjectFinder::QrcUrlFinder::find(const QUrl &fileUrl) const
{
- QString result;
+ FileNameList result;
const auto fileIt = m_fileCache.constFind(fileUrl);
if (fileIt != m_fileCache.cend())
return fileIt.value();
@@ -448,10 +476,7 @@ QString FileInProjectFinder::QrcUrlFinder::find(const QUrl &fileUrl) const
continue;
QStringList hits;
qrcParser->collectFilesAtPath(QrcParser::normalizedQrcFilePath(fileUrl.toString()), &hits);
- if (!hits.empty()) {
- result = hits.first();
- break;
- }
+ result = transform(hits, [](const QString &fp) { return FileName::fromString(fp); });
}
m_fileCache.insert(fileUrl, result);
return result;
@@ -464,4 +489,16 @@ void FileInProjectFinder::QrcUrlFinder::setProjectFiles(const FileNameList &proj
m_parserCache.clear();
}
+FileName chooseFileFromList(const FileNameList &candidates)
+{
+ if (candidates.length() == 1)
+ return candidates.first();
+ QMenu filesMenu;
+ for (const FileName &candidate : candidates)
+ filesMenu.addAction(candidate.toUserOutput());
+ if (const QAction * const action = filesMenu.exec(QCursor::pos()))
+ return FileName::fromUserInput(action->text());
+ return FileName();
+}
+
} // namespace Utils
diff --git a/src/libs/utils/fileinprojectfinder.h b/src/libs/utils/fileinprojectfinder.h
index 2b1dc94090..ac8cd0a588 100644
--- a/src/libs/utils/fileinprojectfinder.h
+++ b/src/libs/utils/fileinprojectfinder.h
@@ -55,7 +55,7 @@ public:
void addMappedPath(const FileName &localFilePath, const QString &remoteFilePath);
- QString findFile(const QUrl &fileUrl, bool *success = nullptr) const;
+ FileNameList findFile(const QUrl &fileUrl, bool *success = nullptr) const;
bool findFileOrDirectory(const QString &originalPath, FileHandler fileHandler = nullptr,
DirectoryHandler directoryHandler = nullptr) const;
@@ -71,17 +71,17 @@ private:
};
struct CacheEntry {
- QString path;
+ QStringList paths;
int matchLength = 0;
};
class QrcUrlFinder {
public:
- QString find(const QUrl &fileUrl) const;
+ FileNameList find(const QUrl &fileUrl) const;
void setProjectFiles(const FileNameList &projectFiles);
private:
FileNameList m_allQrcFiles;
- mutable QHash<QUrl, QString> m_fileCache;
+ mutable QHash<QUrl, FileNameList> m_fileCache;
mutable QHash<FileName, QSharedPointer<QrcParser>> m_parserCache;
};
@@ -92,11 +92,11 @@ private:
QStringList filesWithSameFileName(const QString &fileName) const;
QStringList pathSegmentsWithSameName(const QString &path) const;
- bool handleSuccess(const QString &originalPath, const QString &found, int confidence,
+ bool handleSuccess(const QString &originalPath, const QStringList &found, int confidence,
const char *where) const;
static int commonPostFixLength(const QString &candidatePath, const QString &filePathToFind);
- static QString bestMatch(const QStringList &filePaths, const QString &filePathToFind);
+ static QStringList bestMatches(const QStringList &filePaths, const QString &filePathToFind);
FileName m_projectDir;
FileName m_sysroot;
@@ -108,4 +108,6 @@ private:
QrcUrlFinder m_qrcUrlFinder;
};
+QTCREATOR_UTILS_EXPORT FileName chooseFileFromList(const FileNameList &candidates);
+
} // namespace Utils
diff --git a/src/plugins/debugger/console/consoleview.cpp b/src/plugins/debugger/console/consoleview.cpp
index 9969bfb0f5..c6387cc9e0 100644
--- a/src/plugins/debugger/console/consoleview.cpp
+++ b/src/plugins/debugger/console/consoleview.cpp
@@ -218,7 +218,8 @@ void ConsoleView::onRowActivated(const QModelIndex &index)
if (!index.isValid())
return;
- const QFileInfo fi(m_finder.findFile(model()->data(index, ConsoleItem::FileRole).toString()));
+ const QFileInfo fi = m_finder.findFile(model()->data(index, ConsoleItem::FileRole).toString())
+ .first().toFileInfo();
if (fi.exists() && fi.isFile() && fi.isReadable()) {
Core::EditorManager::openEditorAt(fi.canonicalFilePath(),
model()->data(index, ConsoleItem::LineRole).toInt());
diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp
index 7399c99b7f..3c9d5ce37f 100644
--- a/src/plugins/debugger/debuggerengine.cpp
+++ b/src/plugins/debugger/debuggerengine.cpp
@@ -1828,7 +1828,7 @@ QString DebuggerEngine::toFileInProject(const QUrl &fileUrl)
d->m_fileFinder.setAdditionalSearchDirectories(rp.additionalSearchDirectories);
d->m_fileFinder.setSysroot(rp.sysRoot);
- return d->m_fileFinder.findFile(fileUrl);
+ return d->m_fileFinder.findFile(fileUrl).first().toString();
}
QString DebuggerEngine::expand(const QString &string) const
diff --git a/src/plugins/perfprofiler/perfprofilertool.cpp b/src/plugins/perfprofiler/perfprofilertool.cpp
index 57de5ce14a..662e9ef548 100644
--- a/src/plugins/perfprofiler/perfprofilertool.cpp
+++ b/src/plugins/perfprofiler/perfprofilertool.cpp
@@ -540,7 +540,7 @@ void PerfProfilerTool::gotoSourceLocation(QString filePath, int lineNumber, int
QFileInfo fi(filePath);
if (!fi.isAbsolute() || !fi.exists() || !fi.isReadable()) {
- fi.setFile(m_fileFinder.findFile(filePath));
+ fi.setFile(m_fileFinder.findFile(filePath).first().toString());
if (!fi.exists() || !fi.isReadable())
return;
}
diff --git a/src/plugins/projectexplorer/fileinsessionfinder.cpp b/src/plugins/projectexplorer/fileinsessionfinder.cpp
index 15164f9fcc..667cbdd22e 100644
--- a/src/plugins/projectexplorer/fileinsessionfinder.cpp
+++ b/src/plugins/projectexplorer/fileinsessionfinder.cpp
@@ -29,7 +29,6 @@
#include "session.h"
#include <utils/fileinprojectfinder.h>
-#include <utils/fileutils.h>
#include <QUrl>
@@ -43,7 +42,7 @@ class FileInSessionFinder : public QObject
public:
FileInSessionFinder();
- FileName doFindFile(const FileName &filePath);
+ FileNameList doFindFile(const FileName &filePath);
void invalidateFinder() { m_finderIsUpToDate = false; }
private:
@@ -65,7 +64,7 @@ FileInSessionFinder::FileInSessionFinder()
});
}
-FileName FileInSessionFinder::doFindFile(const FileName &filePath)
+FileNameList FileInSessionFinder::doFindFile(const FileName &filePath)
{
if (!m_finderIsUpToDate) {
m_finder.setProjectDirectory(SessionManager::startupProject()
@@ -77,10 +76,10 @@ FileName FileInSessionFinder::doFindFile(const FileName &filePath)
m_finder.setProjectFiles(allFiles);
m_finderIsUpToDate = true;
}
- return FileName::fromString(m_finder.findFile(QUrl::fromLocalFile(filePath.toString())));
+ return m_finder.findFile(QUrl::fromLocalFile(filePath.toString()));
}
-FileName findFileInSession(const FileName &filePath)
+FileNameList findFileInSession(const FileName &filePath)
{
static FileInSessionFinder finder;
return finder.doFindFile(filePath);
diff --git a/src/plugins/projectexplorer/fileinsessionfinder.h b/src/plugins/projectexplorer/fileinsessionfinder.h
index 8c31a87609..4f08e67d93 100644
--- a/src/plugins/projectexplorer/fileinsessionfinder.h
+++ b/src/plugins/projectexplorer/fileinsessionfinder.h
@@ -25,12 +25,12 @@
#pragma once
-namespace Utils { class FileName; }
+#include <utils/fileutils.h>
namespace ProjectExplorer {
namespace Internal {
-Utils::FileName findFileInSession(const Utils::FileName &filePath);
+Utils::FileNameList findFileInSession(const Utils::FileName &filePath);
} // namespace Internal
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/task.cpp b/src/plugins/projectexplorer/task.cpp
index 83409fadd5..4d334a78e8 100644
--- a/src/plugins/projectexplorer/task.cpp
+++ b/src/plugins/projectexplorer/task.cpp
@@ -25,6 +25,7 @@
#include "task.h"
+#include "fileinsessionfinder.h"
#include "projectexplorerconstants.h"
#include <app/app_version.h>
@@ -34,6 +35,7 @@
#include <utils/utilsicons.h>
#include <utils/qtcassert.h>
+#include <QFileInfo>
#include <QTextStream>
namespace ProjectExplorer
@@ -67,6 +69,13 @@ Task::Task(TaskType type_, const QString &description_,
icon(icon.isNull() ? taskTypeIcon(type_) : icon)
{
++s_nextId;
+ if (!file.isEmpty() && !file.toFileInfo().isAbsolute()) {
+ Utils::FileNameList possiblePaths = Internal::findFileInSession(file);
+ if (possiblePaths.length() == 1)
+ file = possiblePaths.first();
+ else
+ fileCandidates = possiblePaths;
+ }
}
Task Task::compilerMissingTask()
diff --git a/src/plugins/projectexplorer/task.h b/src/plugins/projectexplorer/task.h
index f3e1b76c88..b8b80784aa 100644
--- a/src/plugins/projectexplorer/task.h
+++ b/src/plugins/projectexplorer/task.h
@@ -76,6 +76,7 @@ public:
Options options = AddTextMark | FlashWorthy;
QString description;
Utils::FileName file;
+ Utils::FileNameList fileCandidates;
int line = -1;
int movedLine = -1; // contains a line number if the line was moved in the editor
Core::Id category;
diff --git a/src/plugins/projectexplorer/taskmodel.cpp b/src/plugins/projectexplorer/taskmodel.cpp
index 1780bb4870..1cae2b60a6 100644
--- a/src/plugins/projectexplorer/taskmodel.cpp
+++ b/src/plugins/projectexplorer/taskmodel.cpp
@@ -104,14 +104,8 @@ bool sortById(const Task &task, unsigned int id)
return task.taskId < id;
}
-void TaskModel::addTask(const Task &t)
+void TaskModel::addTask(const Task &task)
{
- Task task = t;
- if (!task.file.isEmpty() && !task.file.toFileInfo().isAbsolute()) {
- const Utils::FileName fullFilePath = findFileInSession(task.file);
- if (!fullFilePath.isEmpty())
- task.file = fullFilePath;
- }
Q_ASSERT(m_categories.keys().contains(task.category));
CategoryData &data = m_categories[task.category];
CategoryData &global = m_categories[Core::Id()];
diff --git a/src/plugins/projectexplorer/taskwindow.cpp b/src/plugins/projectexplorer/taskwindow.cpp
index 38c21fbddd..95f3c08129 100644
--- a/src/plugins/projectexplorer/taskwindow.cpp
+++ b/src/plugins/projectexplorer/taskwindow.cpp
@@ -38,6 +38,7 @@
#include <coreplugin/icontext.h>
#include <utils/algorithm.h>
+#include <utils/fileinprojectfinder.h>
#include <utils/qtcassert.h>
#include <utils/itemviews.h>
#include <utils/utilsicons.h>
@@ -498,6 +499,15 @@ void TaskWindow::triggerDefaultHandler(const QModelIndex &index)
if (task.isNull())
return;
+ if (!task.file.isEmpty() && !task.file.toFileInfo().isAbsolute()
+ && !task.fileCandidates.empty()) {
+ const Utils::FileName userChoice = Utils::chooseFileFromList(task.fileCandidates);
+ if (!userChoice.isEmpty()) {
+ task.file = userChoice;
+ updatedTaskFileName(task.taskId, task.file.toString());
+ }
+ }
+
if (d->m_defaultHandler->canHandle(task)) {
d->m_defaultHandler->handle(task);
} else {
diff --git a/src/plugins/qmlprofiler/qmlprofilerdetailsrewriter.cpp b/src/plugins/qmlprofiler/qmlprofilerdetailsrewriter.cpp
index e96a92623f..cc97f7eb6a 100644
--- a/src/plugins/qmlprofiler/qmlprofilerdetailsrewriter.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerdetailsrewriter.cpp
@@ -112,7 +112,7 @@ void QmlProfilerDetailsRewriter::requestDetailsForLocation(int typeId,
QString QmlProfilerDetailsRewriter::getLocalFile(const QString &remoteFile)
{
- const QString localFile = m_projectFinder.findFile(remoteFile);
+ const QString localFile = m_projectFinder.findFile(remoteFile).first().toString();
const QFileInfo fileInfo(localFile);
if (!fileInfo.exists() || !fileInfo.isReadable())
return QString();
diff --git a/src/plugins/qtsupport/qtoutputformatter.cpp b/src/plugins/qtsupport/qtoutputformatter.cpp
index cb98654858..f554c6e894 100644
--- a/src/plugins/qtsupport/qtoutputformatter.cpp
+++ b/src/plugins/qtsupport/qtoutputformatter.cpp
@@ -211,13 +211,14 @@ void QtOutputFormatter::handleLink(const QString &href)
":(\\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(d->projectFinder.findFile(fileUrl), line, column - 1);
-
+ openEditor(getFileToOpen(fileUrl), line, column - 1);
return;
}
@@ -228,7 +229,7 @@ void QtOutputFormatter::handleLink(const QString &href)
if (qmlLineMatch.hasMatch()) {
const QUrl fileUrl = QUrl(qmlLineMatch.captured(1));
const int line = qmlLineMatch.captured(2).toInt();
- openEditor(d->projectFinder.findFile(fileUrl), line);
+ openEditor(getFileToOpen(fileUrl), line);
return;
}
@@ -257,7 +258,7 @@ void QtOutputFormatter::handleLink(const QString &href)
}
if (!fileName.isEmpty()) {
- fileName = d->projectFinder.findFile(QUrl::fromLocalFile(fileName));
+ fileName = getFileToOpen(QUrl::fromLocalFile(fileName));
openEditor(fileName, line);
return;
}