Skip to content
Snippets Groups Projects
Commit e6ab8296 authored by Erik Verbruggen's avatar Erik Verbruggen
Browse files

Fix for navigating to IDs in the DUI editor.

parent 32e79e10
No related branches found
No related tags found
No related merge requests found
......@@ -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();
......
......@@ -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
#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;
}
#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
......@@ -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;
}
#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;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment