From e6ab82964cbdfb0075395eb9f81fc9d3d621b270 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen <erik.verbruggen@nokia.com> Date: Fri, 11 Sep 2009 15:47:16 +0200 Subject: [PATCH] Fix for navigating to IDs in the DUI editor. --- src/plugins/duieditor/duieditor.cpp | 5 ++- src/plugins/duieditor/duieditor.pro | 6 ++- src/plugins/duieditor/idcollector.cpp | 38 ++++++++++++++++ src/plugins/duieditor/idcollector.h | 32 ++++++++++++++ .../duieditor/navigationtokenfinder.cpp | 43 ++++++++----------- src/plugins/duieditor/navigationtokenfinder.h | 9 ++-- 6 files changed, 103 insertions(+), 30 deletions(-) create mode 100644 src/plugins/duieditor/idcollector.cpp create mode 100644 src/plugins/duieditor/idcollector.h diff --git a/src/plugins/duieditor/duieditor.cpp b/src/plugins/duieditor/duieditor.cpp index bacbf9d6240..bca8cb5d5ff 100644 --- a/src/plugins/duieditor/duieditor.cpp +++ b/src/plugins/duieditor/duieditor.cpp @@ -40,6 +40,7 @@ #include "rewriter_p.h" +#include "idcollector.h" #include "navigationtokenfinder.h" #include <coreplugin/icore.h> @@ -715,8 +716,10 @@ TextEditor::BaseTextEditor::Link ScriptEditor::findLinkAt(const QTextCursor &cur if (!doc) return link; + QMap<QString, QmlJS::AST::SourceLocation> idPositions = IdCollector()(doc->program()); + NavigationTokenFinder finder; - if (finder(doc->program(), cursor.position(), resolveTarget)) { + if (finder(doc->program(), cursor.position(), resolveTarget, idPositions)) { link.fileName = file()->fileName(); link.pos = finder.linkPosition(); link.length = finder.linkLength(); diff --git a/src/plugins/duieditor/duieditor.pro b/src/plugins/duieditor/duieditor.pro index 6a400aa9480..66946d7908b 100644 --- a/src/plugins/duieditor/duieditor.pro +++ b/src/plugins/duieditor/duieditor.pro @@ -21,7 +21,8 @@ HEADERS += duieditor.h \ duieditor_global.h \ duimodelmanager.h \ duicodeformatter.h \ - navigationtokenfinder.h + navigationtokenfinder.h \ + idcollector.h SOURCES += duieditor.cpp \ duieditorfactory.cpp \ duieditorplugin.cpp \ @@ -34,5 +35,6 @@ SOURCES += duieditor.cpp \ duimodelmanagerinterface.cpp \ duimodelmanager.cpp \ duicodeformatter.cpp \ - navigationtokenfinder.cpp + navigationtokenfinder.cpp \ + idcollector.cpp RESOURCES += duieditor.qrc diff --git a/src/plugins/duieditor/idcollector.cpp b/src/plugins/duieditor/idcollector.cpp new file mode 100644 index 00000000000..a2ab7cbed73 --- /dev/null +++ b/src/plugins/duieditor/idcollector.cpp @@ -0,0 +1,38 @@ +#include <QDebug> + +#include "idcollector.h" +#include "qmljsast_p.h" +#include "qmljsengine_p.h" + +using namespace QmlJS; +using namespace QmlJS::AST; +using namespace DuiEditor::Internal; + +QMap<QString, QmlJS::AST::SourceLocation> IdCollector::operator()(QmlJS::AST::UiProgram *ast) +{ + _idLocations.clear(); + + Node::accept(ast, this); + + return _idLocations; +} + +bool IdCollector::visit(QmlJS::AST::UiScriptBinding *ast) +{ + if (!(ast->qualifiedId->next) && ast->qualifiedId->name->asString() == "id") + if (ExpressionStatement *e = cast<ExpressionStatement*>(ast->statement)) + if (IdentifierExpression *i = cast<IdentifierExpression*>(e->expression)) + addId(i->name, i->identifierToken); + + return false; +} + +void IdCollector::addId(QmlJS::NameId* id, const QmlJS::AST::SourceLocation &idLocation) +{ + const QString idString = id->asString(); + + qDebug() << "Found ID" << idString; + + if (!_idLocations.contains(idString)) + _idLocations[idString] = idLocation; +} diff --git a/src/plugins/duieditor/idcollector.h b/src/plugins/duieditor/idcollector.h new file mode 100644 index 00000000000..ac10b9c1e47 --- /dev/null +++ b/src/plugins/duieditor/idcollector.h @@ -0,0 +1,32 @@ +#ifndef IDCOLLECTOR_H +#define IDCOLLECTOR_H + +#include <QMap> +#include <QString> + +#include "qmljsastvisitor_p.h" + +namespace QmlJS { class NameId; } + +namespace DuiEditor { +namespace Internal { + +class IdCollector: protected QmlJS::AST::Visitor +{ +public: + QMap<QString, QmlJS::AST::SourceLocation> operator()(QmlJS::AST::UiProgram *ast); + +protected: + virtual bool visit(QmlJS::AST::UiScriptBinding *ast); + +private: + void addId(QmlJS::NameId* id, const QmlJS::AST::SourceLocation &idLocation); + +private: + QMap<QString, QmlJS::AST::SourceLocation> _idLocations; +}; + +} // namespace Internal +} // namespace DuiEditor + +#endif // IDCOLLECTOR_H diff --git a/src/plugins/duieditor/navigationtokenfinder.cpp b/src/plugins/duieditor/navigationtokenfinder.cpp index 12e7ce7365b..df978ccedfd 100644 --- a/src/plugins/duieditor/navigationtokenfinder.cpp +++ b/src/plugins/duieditor/navigationtokenfinder.cpp @@ -9,11 +9,12 @@ using namespace QmlJS; using namespace QmlJS::AST; using namespace DuiEditor::Internal; -bool NavigationTokenFinder::operator()(QmlJS::AST::UiProgram *ast, int position, bool resolveTarget) +bool NavigationTokenFinder::operator()(QmlJS::AST::UiProgram *ast, int position, bool resolveTarget, const QMap<QString, QmlJS::AST::SourceLocation> &idPositions) { _resolveTarget = resolveTarget; - _scopes.clear(); _pos = position; + _idPositions = idPositions; + _scopes.clear(); _linkPosition = -1; _targetLine = -1; @@ -34,7 +35,7 @@ bool NavigationTokenFinder::visit(QmlJS::AST::IdentifierExpression *ast) _linkPosition = ast->identifierToken.offset; _linkLength = ast->identifierToken.length; - if (Node *node = findDeclarationInScopes(ast->name)) + if (Node *node = findDeclarationInScopesOrIds(ast->name)) rememberStartPosition(node); } @@ -122,7 +123,7 @@ bool NavigationTokenFinder::visit(QmlJS::AST::UiQualifiedId *ast) for (UiQualifiedId *iter2 = ast; iter2; iter2 = iter2->next) _linkLength = iter2->identifierToken.end() - _linkPosition; - if (Node *node = findDeclarationInScopes(ast)) + if (Node *node = findDeclarationInScopesOrIds(ast)) rememberStartPosition(node); return false; @@ -150,10 +151,7 @@ bool NavigationTokenFinder::visit(QmlJS::AST::UiSourceElement * /*ast*/) void NavigationTokenFinder::rememberStartPosition(QmlJS::AST::Node *node) { - if (Statement *s = dynamic_cast<Statement*>(node)) { - _targetLine = s->firstSourceLocation().startLine; - _targetColumn = s->firstSourceLocation().startColumn; - } else if (UiObjectMember *om = dynamic_cast<UiObjectMember*>(node)) { + if (UiObjectMember *om = dynamic_cast<UiObjectMember*>(node)) { _targetLine = om->firstSourceLocation().startLine; _targetColumn = om->firstSourceLocation().startColumn; } else if (VariableDeclaration *vd = cast<VariableDeclaration*>(node)) { @@ -164,18 +162,10 @@ void NavigationTokenFinder::rememberStartPosition(QmlJS::AST::Node *node) } } -static inline bool isId(QmlJS::AST::UiQualifiedId *ast) -{ - return !(ast->next) && ast->name->asString() == "id"; -} - -static inline QString idToString(QmlJS::AST::Statement *stmt) +void NavigationTokenFinder::rememberStartPosition(const QmlJS::AST::SourceLocation &location) { - if (ExpressionStatement *e = cast<ExpressionStatement*>(stmt)) - if (IdentifierExpression *i = cast<IdentifierExpression*>(e->expression)) - return i->name->asString(); - - return QString::null; + _targetLine = location.startLine; + _targetColumn = location.startColumn; } static QmlJS::AST::Node *findDeclaration(const QString &nameId, QmlJS::AST::UiObjectMember *m) @@ -189,9 +179,6 @@ static QmlJS::AST::Node *findDeclaration(const QString &nameId, QmlJS::AST::UiOb } else if (UiArrayBinding *a = cast<UiArrayBinding*>(m)) { if (!(a->qualifiedId->next) && a->qualifiedId->name->asString() == nameId) return a; - } else if (UiScriptBinding *s = cast<UiScriptBinding*>(m)) { - if (isId(s->qualifiedId) && nameId == idToString(s->statement)) - return s->statement; } return 0; @@ -248,7 +235,7 @@ static QmlJS::AST::Node *findDeclarationInNode(QmlJS::AST::UiQualifiedId *qualif return findDeclarationInNode(qualifiedId->next, findDeclarationAsDirectChild(qualifiedId->name->asString(), node)); } -QmlJS::AST::Node *NavigationTokenFinder::findDeclarationInScopes(QmlJS::NameId *nameId) +QmlJS::AST::Node *NavigationTokenFinder::findDeclarationInScopesOrIds(QmlJS::NameId *nameId) { if (!_resolveTarget) return 0; @@ -262,10 +249,14 @@ QmlJS::AST::Node *NavigationTokenFinder::findDeclarationInScopes(QmlJS::NameId * return result; } + if (_idPositions.contains(nameAsString)) { + rememberStartPosition(_idPositions[nameAsString]); + } + return 0; } -QmlJS::AST::Node *NavigationTokenFinder::findDeclarationInScopes(QmlJS::AST::UiQualifiedId *qualifiedId) +QmlJS::AST::Node *NavigationTokenFinder::findDeclarationInScopesOrIds(QmlJS::AST::UiQualifiedId *qualifiedId) { if (!_resolveTarget) return 0; @@ -280,5 +271,9 @@ QmlJS::AST::Node *NavigationTokenFinder::findDeclarationInScopes(QmlJS::AST::UiQ return findDeclarationInNode(qualifiedId->next, result); } + if (_idPositions.contains(nameAsString)) { + rememberStartPosition(_idPositions[nameAsString]); + } + return 0; } diff --git a/src/plugins/duieditor/navigationtokenfinder.h b/src/plugins/duieditor/navigationtokenfinder.h index ab8c23c0d42..bcd8c73b46b 100644 --- a/src/plugins/duieditor/navigationtokenfinder.h +++ b/src/plugins/duieditor/navigationtokenfinder.h @@ -1,6 +1,7 @@ #ifndef NAVIGATIONTOKENFINDER_H #define NAVIGATIONTOKENFINDER_H +#include <QMap> #include <QStack> #include <QString> @@ -16,7 +17,7 @@ namespace Internal { class NavigationTokenFinder: protected QmlJS::AST::Visitor { public: - bool operator()(QmlJS::AST::UiProgram *ast, int position, bool resolveTarget); + bool operator()(QmlJS::AST::UiProgram *ast, int position, bool resolveTarget, const QMap<QString, QmlJS::AST::SourceLocation> &idPositions); bool targetFound() const { return _targetLine != -1; } bool linkFound() const { return _linkPosition != -1; } @@ -42,14 +43,16 @@ protected: virtual void endVisit(QmlJS::AST::UiObjectDefinition *); private: - QmlJS::AST::Node *findDeclarationInScopes(QmlJS::AST::UiQualifiedId *ast); - QmlJS::AST::Node *findDeclarationInScopes(QmlJS::NameId *id); + QmlJS::AST::Node *findDeclarationInScopesOrIds(QmlJS::AST::UiQualifiedId *ast); + QmlJS::AST::Node *findDeclarationInScopesOrIds(QmlJS::NameId *id); void rememberStartPosition(QmlJS::AST::Node *node); + void rememberStartPosition(const QmlJS::AST::SourceLocation &location); private: bool _resolveTarget; quint32 _pos; + QMap<QString, QmlJS::AST::SourceLocation> _idPositions; int _linkPosition; int _linkLength; int _targetLine; -- GitLab