summaryrefslogtreecommitdiff
path: root/src/plugins/qmljstools/qmljslocatordata.cpp
diff options
context:
space:
mode:
authorChristian Kamm <christian.d.kamm@nokia.com>2010-11-16 13:54:50 +0100
committerChristian Kamm <christian.d.kamm@nokia.com>2010-11-16 15:27:26 +0100
commit7dfb2bd577bbfb009e61de262721a2e57c1bcf66 (patch)
treef6a4eaaa564ad6006e09a382e1961d64cf489142 /src/plugins/qmljstools/qmljslocatordata.cpp
parent6c9f32ba60d4bdcb446f42d4f0861d3a84d7d8da (diff)
downloadqt-creator-7dfb2bd577bbfb009e61de262721a2e57c1bcf66.tar.gz
QmlJS: Add a filter for functions to the locator.
Task-number: QTCREATORBUG-2607 Reviewed-by: Erik Verbruggen
Diffstat (limited to 'src/plugins/qmljstools/qmljslocatordata.cpp')
-rw-r--r--src/plugins/qmljstools/qmljslocatordata.cpp218
1 files changed, 218 insertions, 0 deletions
diff --git a/src/plugins/qmljstools/qmljslocatordata.cpp b/src/plugins/qmljstools/qmljslocatordata.cpp
new file mode 100644
index 0000000000..4b9b45e24a
--- /dev/null
+++ b/src/plugins/qmljstools/qmljslocatordata.cpp
@@ -0,0 +1,218 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "qmljslocatordata.h"
+
+#include <qmljs/qmljsmodelmanagerinterface.h>
+#include <qmljs/qmljsbind.h>
+#include <qmljs/qmljsinterpreter.h>
+#include <qmljs/parser/qmljsast_p.h>
+
+using namespace QmlJSTools::Internal;
+using namespace QmlJS;
+using namespace QmlJS::Interpreter;
+using namespace QmlJS::AST;
+
+LocatorData::LocatorData(QObject *parent)
+ : QObject(parent)
+{
+ QmlJS::ModelManagerInterface *manager = QmlJS::ModelManagerInterface::instance();
+
+ connect(manager, SIGNAL(documentUpdated(QmlJS::Document::Ptr)),
+ this, SLOT(onDocumentUpdated(QmlJS::Document::Ptr)));
+ connect(manager, SIGNAL(aboutToRemoveFiles(QStringList)),
+ this, SLOT(onAboutToRemoveFiles(QStringList)));
+}
+
+LocatorData::~LocatorData()
+{}
+
+namespace {
+static QString findId(UiObjectInitializer *initializer)
+{
+ if (!initializer)
+ return QString();
+ for (UiObjectMemberList *member = initializer->members; member; member = member->next) {
+ if (UiScriptBinding *script = cast<UiScriptBinding *>(member->member)) {
+ if (!script->qualifiedId || !script->qualifiedId->name || script->qualifiedId->next)
+ continue;
+ if (script->qualifiedId->name->asString() != QLatin1String("id"))
+ continue;
+ if (ExpressionStatement *expStmt = cast<ExpressionStatement *>(script->statement)) {
+ if (IdentifierExpression *identExp = cast<IdentifierExpression *>(expStmt->expression)) {
+ if (identExp->name)
+ return identExp->name->asString();
+ }
+ }
+ }
+ }
+ return QString();
+}
+
+class FunctionFinder : protected AST::Visitor
+{
+ QList<LocatorData::Entry> m_entries;
+ Document::Ptr m_doc;
+ QString m_context;
+ QString m_documentContext;
+
+public:
+ FunctionFinder()
+ {}
+
+ QList<LocatorData::Entry> run(const Document::Ptr &doc)
+ {
+ m_doc = doc;
+ if (!doc->componentName().isEmpty()) {
+ m_documentContext = doc->componentName();
+ } else {
+ m_documentContext = QFileInfo(doc->fileName()).fileName();
+ }
+ accept(doc->ast(), m_documentContext);
+ return m_entries;
+ }
+
+protected:
+ QString contextString(const QString &extra)
+ {
+ return QString("%1, %2").arg(extra, m_documentContext);
+ }
+
+ LocatorData::Entry basicEntry(SourceLocation loc)
+ {
+ LocatorData::Entry entry;
+ entry.type = LocatorData::Function;
+ entry.extraInfo = m_context;
+ entry.fileName = m_doc->fileName();
+ entry.line = loc.startLine;
+ entry.column = loc.startColumn - 1;
+ return entry;
+ }
+
+ void accept(Node *ast, const QString &context)
+ {
+ const QString old = m_context;
+ m_context = context;
+ Node::accept(ast, this);
+ m_context = old;
+ }
+
+ bool visit(FunctionDeclaration *ast)
+ {
+ return visit(static_cast<FunctionExpression *>(ast));
+ }
+
+ bool visit(FunctionExpression *ast)
+ {
+ if (!ast->name)
+ return true;
+
+ LocatorData::Entry entry = basicEntry(ast->identifierToken);
+
+ entry.type = LocatorData::Function;
+ entry.displayName = ast->name->asString();
+ entry.displayName += QLatin1Char('(');
+ for (FormalParameterList *it = ast->formals; it; it = it->next) {
+ if (it != ast->formals)
+ entry.displayName += QLatin1String(", ");
+ if (it->name)
+ entry.displayName += it->name->asString();
+ }
+ entry.displayName += QLatin1Char(')');
+ entry.symbolName = entry.displayName;
+
+ m_entries += entry;
+
+ accept(ast->body, contextString(QString("function %1").arg(entry.displayName)));
+ return false;
+ }
+
+ bool visit(UiScriptBinding *ast)
+ {
+ if (!ast->qualifiedId)
+ return true;
+ const QString qualifiedIdString = Bind::toString(ast->qualifiedId);
+
+ if (cast<Block *>(ast->statement)) {
+ LocatorData::Entry entry = basicEntry(ast->qualifiedId->identifierToken);
+ entry.displayName = qualifiedIdString;
+ entry.symbolName = qualifiedIdString;
+ m_entries += entry;
+ }
+
+ accept(ast->statement, contextString(Bind::toString(ast->qualifiedId)));
+ return false;
+ }
+
+ bool visit(UiObjectBinding *ast)
+ {
+ if (!ast->qualifiedTypeNameId)
+ return true;
+
+ QString context = Bind::toString(ast->qualifiedTypeNameId);
+ const QString id = findId(ast->initializer);
+ if (!id.isEmpty())
+ context = QString("%1 (%2)").arg(id, context);
+ accept(ast->initializer, contextString(context));
+ return false;
+ }
+
+ bool visit(UiObjectDefinition *ast)
+ {
+ if (!ast->qualifiedTypeNameId)
+ return true;
+
+ QString context = Bind::toString(ast->qualifiedTypeNameId);
+ const QString id = findId(ast->initializer);
+ if (!id.isEmpty())
+ context = QString("%1 (%2)").arg(id, context);
+ accept(ast->initializer, contextString(context));
+ return false;
+ }
+};
+} // anonymous namespace
+
+QHash<QString, QList<LocatorData::Entry> > LocatorData::entries() const
+{
+ return m_entries;
+}
+
+void LocatorData::onDocumentUpdated(const QmlJS::Document::Ptr &doc)
+{
+ QList<Entry> entries = FunctionFinder().run(doc);
+ m_entries.insert(doc->fileName(), entries);
+}
+
+void LocatorData::onAboutToRemoveFiles(const QStringList &files)
+{
+ foreach (const QString &file, files) {
+ m_entries.remove(file);
+ }
+}
+