Commit e6ab8296 authored by Erik Verbruggen's avatar Erik Verbruggen

Fix for navigating to IDs in the DUI editor.

parent 32e79e10
......@@ -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;
......
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