From 51a9ff7d4ead754838b675c3184ea7f56e0eb2fe Mon Sep 17 00:00:00 2001
From: Kai Koehne <kai.koehne@nokia.com>
Date: Tue, 19 Jul 2011 17:48:57 +0200
Subject: [PATCH] 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>
---
 src/libs/utils/fileinprojectfinder.cpp        | 33 +++++++++++++++----
 src/libs/utils/fileinprojectfinder.h          |  3 +-
 src/plugins/debugger/qml/qmlengine.cpp        | 19 ++---------
 src/plugins/debugger/qml/qmlengine.h          |  2 +-
 .../qmljsinspector/qmljsclientproxy.cpp       | 10 +++---
 src/plugins/qmljsinspector/qmljsinspector.cpp | 10 ++----
 src/plugins/qmljsinspector/qmljsinspector.h   |  2 +-
 .../qmlprofiler/qmlprofilereventview.cpp      |  6 ++--
 src/plugins/qmlprofiler/qmlprofilertool.cpp   |  3 +-
 src/plugins/qtsupport/qtoutputformatter.cpp   | 10 +++---
 10 files changed, 51 insertions(+), 47 deletions(-)

diff --git a/src/libs/utils/fileinprojectfinder.cpp b/src/libs/utils/fileinprojectfinder.cpp
index f8253e48f1f..aa57785dd57 100644
--- a/src/libs/utils/fileinprojectfinder.cpp
+++ b/src/libs/utils/fileinprojectfinder.cpp
@@ -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);
diff --git a/src/libs/utils/fileinprojectfinder.h b/src/libs/utils/fileinprojectfinder.h
index cecbe0cc6dc..aff9b214d3e 100644
--- a/src/libs/utils/fileinprojectfinder.h
+++ b/src/libs/utils/fileinprojectfinder.h
@@ -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;
diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp
index fb7c80da7a7..4634729ec7f 100644
--- a/src/plugins/debugger/qml/qmlengine.cpp
+++ b/src/plugins/debugger/qml/qmlengine.cpp
@@ -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;
diff --git a/src/plugins/debugger/qml/qmlengine.h b/src/plugins/debugger/qml/qmlengine.h
index c4c7e421d59..9dd2b82e219 100644
--- a/src/plugins/debugger/qml/qmlengine.h
+++ b/src/plugins/debugger/qml/qmlengine.h
@@ -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;
diff --git a/src/plugins/qmljsinspector/qmljsclientproxy.cpp b/src/plugins/qmljsinspector/qmljsclientproxy.cpp
index aff9c46e7ff..e2257459d86 100644
--- a/src/plugins/qmljsinspector/qmljsclientproxy.cpp
+++ b/src/plugins/qmljsinspector/qmljsclientproxy.cpp
@@ -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);
diff --git a/src/plugins/qmljsinspector/qmljsinspector.cpp b/src/plugins/qmljsinspector/qmljsinspector.cpp
index 5a2ffbdcc55..bc204ded6ad 100644
--- a/src/plugins/qmljsinspector/qmljsinspector.cpp
+++ b/src/plugins/qmljsinspector/qmljsinspector.cpp
@@ -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)
diff --git a/src/plugins/qmljsinspector/qmljsinspector.h b/src/plugins/qmljsinspector/qmljsinspector.h
index 697011f41e8..72762e363b7 100644
--- a/src/plugins/qmljsinspector/qmljsinspector.h
+++ b/src/plugins/qmljsinspector/qmljsinspector.h
@@ -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;
diff --git a/src/plugins/qmlprofiler/qmlprofilereventview.cpp b/src/plugins/qmlprofiler/qmlprofilereventview.cpp
index 7bfa178fd73..62c990716ac 100644
--- a/src/plugins/qmlprofiler/qmlprofilereventview.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilereventview.cpp
@@ -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);
     }
 
diff --git a/src/plugins/qmlprofiler/qmlprofilertool.cpp b/src/plugins/qmlprofiler/qmlprofilertool.cpp
index a72872bce04..50d31c25603 100644
--- a/src/plugins/qmlprofiler/qmlprofilertool.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilertool.cpp
@@ -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);
diff --git a/src/plugins/qtsupport/qtoutputformatter.cpp b/src/plugins/qtsupport/qtoutputformatter.cpp
index 036521ac529..6d75f159096 100644
--- a/src/plugins/qtsupport/qtoutputformatter.cpp
+++ b/src/plugins/qtsupport/qtoutputformatter.cpp
@@ -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;
-- 
GitLab