forked from qt-creator/qt-creator
QmlJS: Add a filter for functions to the locator.
Task-number: QTCREATORBUG-2607 Reviewed-by: Erik Verbruggen
This commit is contained in:
@@ -16,5 +16,6 @@ Alternatively, this plugin may be used under the terms of the GNU Lesser General
|
||||
<dependencyList>
|
||||
<dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/>
|
||||
<dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/>
|
||||
<dependency name=\"Locator\" version=\"$$QTCREATOR_VERSION\"/>
|
||||
</dependencyList>
|
||||
</plugin>
|
||||
|
115
src/plugins/qmljstools/qmljsfunctionfilter.cpp
Normal file
115
src/plugins/qmljstools/qmljsfunctionfilter.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** 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 "qmljsfunctionfilter.h"
|
||||
#include "qmljslocatordata.h"
|
||||
|
||||
#include <texteditor/itexteditor.h>
|
||||
#include <texteditor/basetexteditor.h>
|
||||
|
||||
#include <QtCore/QStringMatcher>
|
||||
|
||||
using namespace QmlJSTools::Internal;
|
||||
|
||||
Q_DECLARE_METATYPE(LocatorData::Entry);
|
||||
|
||||
FunctionFilter::FunctionFilter(LocatorData *data, QObject *parent)
|
||||
: Locator::ILocatorFilter(parent)
|
||||
, m_data(data)
|
||||
{
|
||||
setShortcutString(QString(QLatin1Char('m')));
|
||||
setIncludedByDefault(false);
|
||||
}
|
||||
|
||||
FunctionFilter::~FunctionFilter()
|
||||
{ }
|
||||
|
||||
void FunctionFilter::refresh(QFutureInterface<void> &)
|
||||
{
|
||||
}
|
||||
|
||||
static bool compareLexigraphically(const Locator::FilterEntry &a,
|
||||
const Locator::FilterEntry &b)
|
||||
{
|
||||
return a.displayName < b.displayName;
|
||||
}
|
||||
|
||||
QList<Locator::FilterEntry> FunctionFilter::matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString &origEntry)
|
||||
{
|
||||
QString entry = trimWildcards(origEntry);
|
||||
QList<Locator::FilterEntry> goodEntries;
|
||||
QList<Locator::FilterEntry> betterEntries;
|
||||
const QChar asterisk = QLatin1Char('*');
|
||||
QStringMatcher matcher(entry, Qt::CaseInsensitive);
|
||||
const QRegExp regexp(asterisk + entry+ asterisk, Qt::CaseInsensitive, QRegExp::Wildcard);
|
||||
if (!regexp.isValid())
|
||||
return goodEntries;
|
||||
bool hasWildcard = (entry.contains(asterisk) || entry.contains('?'));
|
||||
|
||||
QHashIterator<QString, QList<LocatorData::Entry> > it(m_data->entries());
|
||||
while (it.hasNext()) {
|
||||
if (future.isCanceled())
|
||||
break;
|
||||
|
||||
it.next();
|
||||
|
||||
const QList<LocatorData::Entry> items = it.value();
|
||||
foreach (const LocatorData::Entry &info, items) {
|
||||
if (info.type != LocatorData::Function)
|
||||
continue;
|
||||
if ((hasWildcard && regexp.exactMatch(info.symbolName))
|
||||
|| (!hasWildcard && matcher.indexIn(info.symbolName) != -1)) {
|
||||
|
||||
QVariant id = qVariantFromValue(info);
|
||||
Locator::FilterEntry filterEntry(this, info.displayName, id/*, info.icon*/);
|
||||
filterEntry.extraInfo = info.extraInfo;
|
||||
|
||||
if (info.symbolName.startsWith(entry))
|
||||
betterEntries.append(filterEntry);
|
||||
else
|
||||
goodEntries.append(filterEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (goodEntries.size() < 1000)
|
||||
qSort(goodEntries.begin(), goodEntries.end(), compareLexigraphically);
|
||||
if (betterEntries.size() < 1000)
|
||||
qSort(betterEntries.begin(), betterEntries.end(), compareLexigraphically);
|
||||
|
||||
betterEntries += goodEntries;
|
||||
return betterEntries;
|
||||
}
|
||||
|
||||
void FunctionFilter::accept(Locator::FilterEntry selection) const
|
||||
{
|
||||
const LocatorData::Entry entry = qvariant_cast<LocatorData::Entry>(selection.internalData);
|
||||
TextEditor::BaseTextEditor::openEditorAt(entry.fileName, entry.line, entry.column,
|
||||
QString(), Core::EditorManager::ModeSwitch);
|
||||
}
|
61
src/plugins/qmljstools/qmljsfunctionfilter.h
Normal file
61
src/plugins/qmljstools/qmljsfunctionfilter.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef QMLJSFUNCTIONFILTER_H
|
||||
#define QMLJSFUNCTIONFILTER_H
|
||||
|
||||
#include <locator/ilocatorfilter.h>
|
||||
|
||||
namespace QmlJSTools {
|
||||
namespace Internal {
|
||||
|
||||
class LocatorData;
|
||||
|
||||
class FunctionFilter : public Locator::ILocatorFilter
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit FunctionFilter(LocatorData *data, QObject *parent = 0);
|
||||
~FunctionFilter();
|
||||
|
||||
QString displayName() const { return tr("Functions"); }
|
||||
QString id() const { return QLatin1String("Functions"); }
|
||||
Priority priority() const { return Medium; }
|
||||
QList<Locator::FilterEntry> matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString &entry);
|
||||
void accept(Locator::FilterEntry selection) const;
|
||||
void refresh(QFutureInterface<void> &future);
|
||||
|
||||
private:
|
||||
LocatorData *m_data;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace QmlJSTools
|
||||
|
||||
#endif // QMLJSFUNCTIONFILTER_H
|
218
src/plugins/qmljstools/qmljslocatordata.cpp
Normal file
218
src/plugins/qmljstools/qmljslocatordata.cpp
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
|
78
src/plugins/qmljstools/qmljslocatordata.h
Normal file
78
src/plugins/qmljstools/qmljslocatordata.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef QMLJSLOCATORDATA_H
|
||||
#define QMLJSLOCATORDATA_H
|
||||
|
||||
#include <qmljs/qmljsdocument.h>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QHash>
|
||||
|
||||
namespace QmlJSTools {
|
||||
namespace Internal {
|
||||
|
||||
class LocatorData : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit LocatorData(QObject *parent = 0);
|
||||
~LocatorData();
|
||||
|
||||
enum EntryType
|
||||
{
|
||||
Function,
|
||||
};
|
||||
|
||||
class Entry
|
||||
{
|
||||
public:
|
||||
EntryType type;
|
||||
QString symbolName;
|
||||
QString displayName;
|
||||
QString extraInfo;
|
||||
QString fileName;
|
||||
int line;
|
||||
int column;
|
||||
};
|
||||
|
||||
QHash<QString, QList<Entry> > entries() const;
|
||||
|
||||
private slots:
|
||||
void onDocumentUpdated(const QmlJS::Document::Ptr &doc);
|
||||
void onAboutToRemoveFiles(const QStringList &files);
|
||||
|
||||
private:
|
||||
QHash<QString, QList<Entry> > m_entries;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace QmlJSTools
|
||||
|
||||
#endif // QMLJSLOCATORDATA_H
|
@@ -12,11 +12,15 @@ HEADERS += \
|
||||
$$PWD/qmljsmodelmanager.h \
|
||||
$$PWD/qmljsqtstylecodeformatter.h \
|
||||
$$PWD/qmljsrefactoringchanges.h \
|
||||
$$PWD/qmljsplugindumper.h
|
||||
$$PWD/qmljsplugindumper.h \
|
||||
$$PWD/qmljsfunctionfilter.h \
|
||||
$$PWD/qmljslocatordata.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/qmljstoolsplugin.cpp \
|
||||
$$PWD/qmljsmodelmanager.cpp \
|
||||
$$PWD/qmljsqtstylecodeformatter.cpp \
|
||||
$$PWD/qmljsrefactoringchanges.cpp \
|
||||
$$PWD/qmljsplugindumper.cpp
|
||||
$$PWD/qmljsplugindumper.cpp \
|
||||
$$PWD/qmljsfunctionfilter.cpp \
|
||||
$$PWD/qmljslocatordata.cpp
|
||||
|
@@ -29,6 +29,8 @@
|
||||
|
||||
#include "qmljstoolsplugin.h"
|
||||
#include "qmljsmodelmanager.h"
|
||||
#include "qmljsfunctionfilter.h"
|
||||
#include "qmljslocatordata.h"
|
||||
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
|
||||
@@ -74,6 +76,10 @@ bool QmlJSToolsPlugin::initialize(const QStringList &arguments, QString *error)
|
||||
// m_modelManager, SLOT(updateSourceFiles(QStringList)));
|
||||
addAutoReleasedObject(m_modelManager);
|
||||
|
||||
LocatorData *locatorData = new LocatorData;
|
||||
addAutoReleasedObject(locatorData);
|
||||
addAutoReleasedObject(new FunctionFilter(locatorData));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user