diff options
author | Xavier BESSON <developer@xavi-b.fr> | 2022-12-07 23:19:07 +0100 |
---|---|---|
committer | Xavier BESSON (Personal) <developer@xavi-b.fr> | 2023-12-20 15:03:39 +0000 |
commit | 90368e2bba9c71ab6e3fc0b106f1a74942866ebb (patch) | |
tree | 409c166603d54e90270b95e6caac3b9b2d773600 | |
parent | 42c1b1587484b5dd6dc562e7fd80dacbd041bd33 (diff) |
QmlJsEditor: navigate from QML code to C++ code
Fixes: QTCREATORBUG-28086
Change-Id: I00acfe49b8e74aa057cb59d8c951d477f8ad487e
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
-rw-r--r-- | src/libs/languageutils/fakemetaobject.cpp | 5 | ||||
-rw-r--r-- | src/libs/languageutils/fakemetaobject.h | 4 | ||||
-rw-r--r-- | src/libs/qmljs/qmljsinterpreter.cpp | 8 | ||||
-rw-r--r-- | src/libs/qmljs/qmljsinterpreter.h | 2 | ||||
-rw-r--r-- | src/libs/qmljs/qmljstypedescriptionreader.cpp | 2 | ||||
-rw-r--r-- | src/plugins/qmljseditor/qmljseditor.cpp | 38 |
6 files changed, 52 insertions, 7 deletions
diff --git a/src/libs/languageutils/fakemetaobject.cpp b/src/libs/languageutils/fakemetaobject.cpp index c5e577b6e30..4c553cdc7b5 100644 --- a/src/libs/languageutils/fakemetaobject.cpp +++ b/src/libs/languageutils/fakemetaobject.cpp @@ -269,6 +269,11 @@ QString FakeMetaObject::className() const void FakeMetaObject::setClassName(const QString &name) { m_className = name; } +QString FakeMetaObject::filePath() const +{ return m_filePath; } +void FakeMetaObject::setFilePath(const QString &path) +{ m_filePath = path; } + void FakeMetaObject::addExport(const QString &name, const QString &package, ComponentVersion version) { Export exp; diff --git a/src/libs/languageutils/fakemetaobject.h b/src/libs/languageutils/fakemetaobject.h index c9fcb260110..2eb2ecfb22d 100644 --- a/src/libs/languageutils/fakemetaobject.h +++ b/src/libs/languageutils/fakemetaobject.h @@ -139,6 +139,7 @@ public: private: QString m_className; + QString m_filePath; QList<Export> m_exports; QString m_superName; QList<FakeMetaEnum> m_enums; @@ -160,6 +161,9 @@ public: QString className() const; void setClassName(const QString &name); + QString filePath() const; + void setFilePath(const QString &path); + void addExport(const QString &name, const QString &package, ComponentVersion version); void setExportMetaObjectRevision(int exportIndex, int metaObjectRevision); const QList<Export> exports() const; diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp index 9448ef39b01..5d687d5cd74 100644 --- a/src/libs/qmljs/qmljsinterpreter.cpp +++ b/src/libs/qmljs/qmljsinterpreter.cpp @@ -251,6 +251,14 @@ const CppComponentValue *CppComponentValue::asCppComponentValue() const return this; } +bool CppComponentValue::getSourceLocation(Utils::FilePath *fileName, int *line, int *column) const +{ + *fileName = Utils::FilePath::fromString(m_metaObject->filePath()); + *line = 0; + *column = 0; + return true; +} + void CppComponentValue::processMembers(MemberProcessor *processor) const { // process the meta enums diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h index 8ca9f4ec26c..3fcce78d117 100644 --- a/src/libs/qmljs/qmljsinterpreter.h +++ b/src/libs/qmljs/qmljsinterpreter.h @@ -573,6 +573,8 @@ public: const CppComponentValue *asCppComponentValue() const override; + bool getSourceLocation(Utils::FilePath *fileName, int *line, int *column) const override; + void processMembers(MemberProcessor *processor) const override; const Value *valueForCppName(const QString &typeName) const; diff --git a/src/libs/qmljs/qmljstypedescriptionreader.cpp b/src/libs/qmljs/qmljstypedescriptionreader.cpp index d8d19eefa3c..9d67ad05b23 100644 --- a/src/libs/qmljs/qmljstypedescriptionreader.cpp +++ b/src/libs/qmljs/qmljstypedescriptionreader.cpp @@ -197,6 +197,8 @@ void TypeDescriptionReader::readComponent(UiObjectDefinition *ast) QString name = toString(script->qualifiedId); if (name == QLatin1String("name")) { fmo->setClassName(readStringBinding(script)); + } else if (name == QLatin1String("file")) { + fmo->setFilePath(readStringBinding(script)); } else if (name == QLatin1String("prototype")) { fmo->setSuperclassName(readStringBinding(script)); } else if (name == QLatin1String("defaultProperty")) { diff --git a/src/plugins/qmljseditor/qmljseditor.cpp b/src/plugins/qmljseditor/qmljseditor.cpp index 8219243c29d..710663ae364 100644 --- a/src/plugins/qmljseditor/qmljseditor.cpp +++ b/src/plugins/qmljseditor/qmljseditor.cpp @@ -789,13 +789,18 @@ void QmlJSEditorWidget::findLinkAt(const QTextCursor &cursor, return; } + const ProjectExplorer::Project * const project = ProjectExplorer::ProjectTree::currentProject(); + ProjectExplorer::ProjectNode* projectRootNode = nullptr; + if (project) { + projectRootNode = project->rootProjectNode(); + } + // string literals that could refer to a file link to them if (auto literal = cast<const StringLiteral *>(node)) { const QString &text = literal->value.toString(); if (text.startsWith("qrc:/")) { - const ProjectExplorer::Project * const project = ProjectExplorer::ProjectTree::currentProject(); - if (project && project->rootProjectNode()) { - const ProjectExplorer::Node * const nodeForPath = project->rootProjectNode()->findNode( + if (projectRootNode) { + const ProjectExplorer::Node * const nodeForPath = projectRootNode->findNode( [qrcPath = text.mid(text.indexOf(':') + 1)](ProjectExplorer::Node *n) { if (!n->asFileNode()) return false; @@ -854,14 +859,33 @@ void QmlJSEditorWidget::findLinkAt(const QTextCursor &cursor, if (auto q = AST::cast<const AST::UiQualifiedId *>(node)) { for (const AST::UiQualifiedId *tail = q; tail; tail = tail->next) { - if (! tail->next && cursorPosition <= tail->identifierToken.end()) { - link.linkTextStart = tail->identifierToken.begin(); - link.linkTextEnd = tail->identifierToken.end(); + if (tail->next || !(cursorPosition <= tail->identifierToken.end())) { + continue; + } + + link.linkTextStart = tail->identifierToken.begin(); + link.linkTextEnd = tail->identifierToken.end(); + + if (!value->asCppComponentValue() || !projectRootNode) { processLinkCallback(link); return; } - } + const ProjectExplorer::Node * const nodeForPath = projectRootNode->findNode( + [&fileName](ProjectExplorer::Node *n) { + const auto fileNode = n->asFileNode(); + if (!fileNode) + return false; + Utils::FilePath filePath = n->filePath(); + return filePath.endsWith(fileName.toUserOutput()); + }); + if (nodeForPath) { + link.targetFilePath = nodeForPath->filePath(); + processLinkCallback(link); + return; + } + // else we will process an empty link below to avoid an error dialog + } } else if (auto id = AST::cast<const AST::IdentifierExpression *>(node)) { link.linkTextStart = id->firstSourceLocation().begin(); link.linkTextEnd = id->lastSourceLocation().end(); |