forked from qt-creator/qt-creator
Qml Tooling: Fix debugging & profiling of .qml files loaded from resources
Don't expect that every url specifying a file is a local file url. Instead let FileInProjectFinder handle urls with other schemes gracefully, too. Change-Id: I72457d502ff1caf52f588e8ec41ab260882d1cf5 Reviewed-on: http://codereview.qt.nokia.com/1840 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Christiaan Janssen <christiaan.janssen@nokia.com>
This commit is contained in:
@@ -34,13 +34,14 @@
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtCore/QUrl>
|
||||
|
||||
namespace Utils {
|
||||
|
||||
/*!
|
||||
\class Utils::FileInProjectFinder
|
||||
|
||||
\brief Helper class to find the 'original' file in the project directory for a given file path.
|
||||
\brief Helper class to find the 'original' file in the project directory for a given file url.
|
||||
|
||||
Often files are copied in the build + deploy process. findFile() searches for an existing file
|
||||
in the project directory for a given file path:
|
||||
@@ -86,17 +87,31 @@ void FileInProjectFinder::setProjectFiles(const QStringList &projectFiles)
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the best match for the given originalPath in the project directory.
|
||||
Returns the best match for the given file url in the project directory.
|
||||
|
||||
The method first checks whether the originalPath inside the project directory exists.
|
||||
The method first checks whether the file inside the project directory exists.
|
||||
If not, the leading directory in the path is stripped, and the - now shorter - path is
|
||||
checked for existence. This continues until either the file is found, or the relative path
|
||||
does not contain any directories any more: In this case the originalPath is returned.
|
||||
does not contain any directories any more: In this case the path of the url is returned.
|
||||
|
||||
Second, we walk the list of project files, and search for a file name match there.
|
||||
*/
|
||||
QString FileInProjectFinder::findFile(const QString &originalPath, bool *success) const
|
||||
QString FileInProjectFinder::findFile(const QUrl &fileUrl, bool *success) const
|
||||
{
|
||||
QString originalPath;
|
||||
if (fileUrl.isLocalFile()) {
|
||||
originalPath = fileUrl.toLocalFile();
|
||||
} else {
|
||||
// strip e.g. leading qrc://
|
||||
originalPath = fileUrl.path();
|
||||
}
|
||||
|
||||
if (originalPath.isEmpty()) {
|
||||
if (success)
|
||||
success = false;
|
||||
return originalPath;
|
||||
}
|
||||
|
||||
if (!m_projectDir.isEmpty()) {
|
||||
int prefixToIgnore = -1;
|
||||
const QChar separator = QLatin1Char('/');
|
||||
@@ -132,8 +147,14 @@ QString FileInProjectFinder::findFile(const QString &originalPath, bool *success
|
||||
|
||||
// Strip directories one by one from the beginning of the path,
|
||||
// and see if the new relative path exists in the build directory.
|
||||
if (prefixToIgnore < 0)
|
||||
if (prefixToIgnore < 0) {
|
||||
if (!QFileInfo(originalPath).isAbsolute()
|
||||
&& !originalPath.startsWith(separator)) {
|
||||
prefixToIgnore = 0;
|
||||
} else {
|
||||
prefixToIgnore = originalPath.indexOf(separator);
|
||||
}
|
||||
}
|
||||
while (prefixToIgnore != -1) {
|
||||
QString candidate = originalPath;
|
||||
candidate.remove(0, prefixToIgnore);
|
||||
|
@@ -37,6 +37,7 @@
|
||||
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QUrl>
|
||||
|
||||
namespace Utils {
|
||||
|
||||
@@ -50,7 +51,7 @@ public:
|
||||
|
||||
void setProjectFiles(const QStringList &projectFiles);
|
||||
|
||||
QString findFile(const QString &originalPath, bool *success = 0) const;
|
||||
QString findFile(const QUrl &fileUrl, bool *success = 0) const;
|
||||
|
||||
private:
|
||||
QString m_projectDir;
|
||||
|
@@ -766,27 +766,14 @@ unsigned QmlEngine::debuggerCapabilities() const
|
||||
| AddWatcherCapability;*/
|
||||
}
|
||||
|
||||
QString QmlEngine::toFileInProject(const QString &fileUrl)
|
||||
QString QmlEngine::toFileInProject(const QUrl &fileUrl)
|
||||
{
|
||||
if (fileUrl.isEmpty())
|
||||
return fileUrl;
|
||||
|
||||
const QString path = QUrl(fileUrl).toLocalFile();
|
||||
if (path.isEmpty())
|
||||
return fileUrl;
|
||||
|
||||
if (d->fileFinder.projectDirectory().isEmpty()) {
|
||||
d->fileFinder.setProjectDirectory(startParameters().projectSourceDirectory);
|
||||
d->fileFinder.setProjectFiles(startParameters().projectSourceFiles);
|
||||
}
|
||||
|
||||
// Try to find file with biggest common path in source directory
|
||||
bool fileFound = false;
|
||||
QString fileInProject = d->fileFinder.findFile(path, &fileFound);
|
||||
if (fileFound)
|
||||
return fileInProject;
|
||||
|
||||
return path;
|
||||
return d->fileFinder.findFile(fileUrl);
|
||||
}
|
||||
|
||||
void QmlEngine::messageReceived(const QByteArray &message)
|
||||
@@ -817,7 +804,7 @@ void QmlEngine::messageReceived(const QByteArray &message)
|
||||
StackFrame frame;
|
||||
frame.line = stackFrames.at(i).lineNumber;
|
||||
frame.function = stackFrames.at(i).functionName;
|
||||
frame.file = toFileInProject(stackFrames.at(i).fileUrl);
|
||||
frame.file = toFileInProject(QUrl(stackFrames.at(i).fileUrl));
|
||||
frame.usable = QFileInfo(frame.file).isReadable();
|
||||
frame.level = i + 1;
|
||||
ideStackFrames << frame;
|
||||
|
@@ -153,7 +153,7 @@ private:
|
||||
LogReceive
|
||||
};
|
||||
void logMessage(LogDirection direction, const QString &str);
|
||||
QString toFileInProject(const QString &file);
|
||||
QString toFileInProject(const QUrl &fileUrl);
|
||||
|
||||
private:
|
||||
friend class QmlCppEngine;
|
||||
|
@@ -510,23 +510,23 @@ void ClientProxy::objectTreeFetched(QDeclarativeDebugQuery::State state)
|
||||
|
||||
void ClientProxy::buildDebugIdHashRecursive(const QDeclarativeDebugObjectReference& ref)
|
||||
{
|
||||
QString filename = ref.source().url().toLocalFile();
|
||||
QUrl fileUrl = ref.source().url();
|
||||
int lineNum = ref.source().lineNumber();
|
||||
int colNum = ref.source().columnNumber();
|
||||
int rev = 0;
|
||||
|
||||
// handle the case where the url contains the revision number encoded. (for object created by the debugger)
|
||||
static QRegExp rx("(.*)_(\\d+):(\\d+)$");
|
||||
if (rx.exactMatch(filename)) {
|
||||
filename = rx.cap(1);
|
||||
if (rx.exactMatch(fileUrl.path())) {
|
||||
fileUrl.setPath(rx.cap(1));
|
||||
rev = rx.cap(2).toInt();
|
||||
lineNum += rx.cap(3).toInt() - 1;
|
||||
}
|
||||
|
||||
filename = InspectorUi::instance()->findFileInProject(filename);
|
||||
const QString filePath = InspectorUi::instance()->findFileInProject(fileUrl);
|
||||
|
||||
// append the debug ids in the hash
|
||||
m_debugIdHash[qMakePair<QString, int>(filename, rev)][qMakePair<int, int>(lineNum, colNum)].append(ref.debugId());
|
||||
m_debugIdHash[qMakePair<QString, int>(filePath, rev)][qMakePair<int, int>(lineNum, colNum)].append(ref.debugId());
|
||||
|
||||
foreach (const QDeclarativeDebugObjectReference &it, ref.children())
|
||||
buildDebugIdHashRecursive(it);
|
||||
|
@@ -676,12 +676,8 @@ void InspectorUi::gotoObjectReferenceDefinition(const QDeclarativeDebugObjectRef
|
||||
}
|
||||
|
||||
QDeclarativeDebugFileReference source = obj.source();
|
||||
QString fileName = source.url().toLocalFile();
|
||||
|
||||
if (source.lineNumber() < 0 || !QFile::exists(fileName))
|
||||
return;
|
||||
|
||||
fileName = m_projectFinder.findFile(fileName);
|
||||
const QString fileName = m_projectFinder.findFile(source.url());
|
||||
|
||||
Core::EditorManager *editorManager = Core::EditorManager::instance();
|
||||
Core::IEditor *currentEditor = editorManager->currentEditor();
|
||||
@@ -789,9 +785,9 @@ InspectorUi *InspectorUi::instance()
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
QString InspectorUi::findFileInProject(const QString &originalPath) const
|
||||
QString InspectorUi::findFileInProject(const QUrl &url) const
|
||||
{
|
||||
return m_projectFinder.findFile(originalPath);
|
||||
return m_projectFinder.findFile(url);
|
||||
}
|
||||
|
||||
void InspectorUi::setApplyChangesToQmlInspector(bool applyChanges)
|
||||
|
@@ -95,7 +95,7 @@ public:
|
||||
|
||||
static InspectorUi *instance();
|
||||
|
||||
QString findFileInProject(const QString &file) const;
|
||||
QString findFileInProject(const QUrl &fileUrl) const;
|
||||
|
||||
void setupUi();
|
||||
bool isConnected() const;
|
||||
|
@@ -146,7 +146,7 @@ void QmlProfilerEventStatistics::addRangedEvent(int type, int nestingLevel, int
|
||||
Q_UNUSED(nestingInType);
|
||||
|
||||
const QChar colon = QLatin1Char(':');
|
||||
QString localName, displayName, location, details;
|
||||
QString displayName, location, details;
|
||||
|
||||
if (data.isEmpty())
|
||||
details = tr("Source code not available");
|
||||
@@ -165,8 +165,8 @@ void QmlProfilerEventStatistics::addRangedEvent(int type, int nestingLevel, int
|
||||
displayName = tr("<bytecode>");
|
||||
location = QString("--:%1:%2").arg(QString::number(type), details);
|
||||
} else {
|
||||
localName = QUrl(fileName).toLocalFile();
|
||||
displayName = localName.mid(localName.lastIndexOf(QChar('/')) + 1) + colon + QString::number(line);
|
||||
const QString filePath = QUrl(fileName).path();
|
||||
displayName = filePath.mid(filePath.lastIndexOf(QChar('/')) + 1) + colon + QString::number(line);
|
||||
location = fileName+colon+QString::number(line);
|
||||
}
|
||||
|
||||
|
@@ -420,8 +420,7 @@ void QmlProfilerTool::gotoSourceLocation(const QString &fileUrl, int lineNumber)
|
||||
if (lineNumber < 0 || fileUrl.isEmpty())
|
||||
return;
|
||||
|
||||
const QString fileName = QUrl(fileUrl).toLocalFile();
|
||||
const QString projectFileName = d->m_projectFinder.findFile(fileName);
|
||||
const QString projectFileName = d->m_projectFinder.findFile(fileUrl);
|
||||
|
||||
Core::EditorManager *editorManager = Core::EditorManager::instance();
|
||||
Core::IEditor *editor = editorManager->openEditor(projectFileName);
|
||||
|
@@ -196,11 +196,11 @@ void QtOutputFormatter::handleLink(const QString &href)
|
||||
":(\\d+)$")); // column
|
||||
|
||||
if (qmlLineColumnLink.indexIn(href) != -1) {
|
||||
const QString fileName = QUrl(qmlLineColumnLink.cap(1)).toLocalFile();
|
||||
const QUrl fileUrl = QUrl(qmlLineColumnLink.cap(1));
|
||||
const int line = qmlLineColumnLink.cap(2).toInt();
|
||||
const int column = qmlLineColumnLink.cap(3).toInt();
|
||||
|
||||
TextEditor::BaseTextEditorWidget::openEditorAt(m_projectFinder.findFile(fileName), line, column - 1);
|
||||
TextEditor::BaseTextEditorWidget::openEditorAt(m_projectFinder.findFile(fileUrl), line, column - 1);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -209,9 +209,9 @@ void QtOutputFormatter::handleLink(const QString &href)
|
||||
":(\\d+)$")); // line
|
||||
|
||||
if (qmlLineLink.indexIn(href) != -1) {
|
||||
const QString fileName = QUrl(qmlLineLink.cap(1)).toLocalFile();
|
||||
const QUrl fileUrl = QUrl(qmlLineLink.cap(1));
|
||||
const int line = qmlLineLink.cap(2).toInt();
|
||||
TextEditor::BaseTextEditorWidget::openEditorAt(m_projectFinder.findFile(fileName), line);
|
||||
TextEditor::BaseTextEditorWidget::openEditorAt(m_projectFinder.findFile(fileUrl), line);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -253,7 +253,7 @@ void QtOutputFormatter::handleLink(const QString &href)
|
||||
}
|
||||
} else if (!fi.exists()) {
|
||||
// map possible on-device path to source path
|
||||
fileName = m_projectFinder.findFile(fileName);
|
||||
fileName = m_projectFinder.findFile(QUrl::fromLocalFile(fileName));
|
||||
}
|
||||
TextEditor::BaseTextEditorWidget::openEditorAt(fileName, line, 0);
|
||||
return;
|
||||
|
Reference in New Issue
Block a user