Commit 51a9ff7d authored by Kai Koehne's avatar Kai Koehne

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/1840Reviewed-by: default avatarQt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: default avatarChristiaan Janssen <christiaan.janssen@nokia.com>
parent ebf4212f
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment