2010-06-03 15:49:29 +02:00
|
|
|
/**************************************************************************
|
|
|
|
**
|
|
|
|
** 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 "qmljsquickfix.h"
|
2010-06-14 15:02:05 +02:00
|
|
|
#include "qmljscomponentfromobjectdef.h"
|
2010-06-03 15:49:29 +02:00
|
|
|
#include "qmljseditor.h"
|
2010-06-14 14:52:43 +02:00
|
|
|
#include "qmljsrefactoringchanges.h"
|
2010-06-07 12:12:07 +02:00
|
|
|
#include "qmljs/parser/qmljsast_p.h"
|
2010-06-14 14:52:43 +02:00
|
|
|
|
|
|
|
#include <extensionsystem/pluginmanager.h>
|
|
|
|
|
|
|
|
#include <qmljs/qmljsmodelmanagerinterface.h>
|
|
|
|
|
2010-06-07 12:12:07 +02:00
|
|
|
#include <QtGui/QApplication>
|
2010-06-03 15:49:29 +02:00
|
|
|
#include <QtCore/QDebug>
|
|
|
|
|
2010-06-14 14:52:43 +02:00
|
|
|
using namespace QmlJSEditor;
|
2010-06-03 15:49:29 +02:00
|
|
|
using namespace QmlJSEditor::Internal;
|
2010-06-14 14:52:43 +02:00
|
|
|
using TextEditor::RefactoringChanges;
|
2010-06-03 15:49:29 +02:00
|
|
|
|
2010-06-07 12:12:07 +02:00
|
|
|
class QmlJSQuickFixState: public TextEditor::QuickFixState
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
SemanticInfo semanticInfo;
|
|
|
|
};
|
|
|
|
|
2010-06-07 12:20:07 +02:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
class SplitInitializerOp: public QmlJSQuickFixOperation {
|
|
|
|
public:
|
|
|
|
SplitInitializerOp(TextEditor::BaseTextEditor *editor)
|
|
|
|
: QmlJSQuickFixOperation(editor), _objectInitializer(0)
|
|
|
|
{}
|
|
|
|
|
|
|
|
virtual QString description() const
|
|
|
|
{
|
|
|
|
return QApplication::translate("QmlJSEditor::QuickFix", "Split initializer");
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void createChangeSet()
|
|
|
|
{
|
|
|
|
Q_ASSERT(_objectInitializer != 0);
|
|
|
|
|
|
|
|
for (QmlJS::AST::UiObjectMemberList *it = _objectInitializer->members; it; it = it->next) {
|
|
|
|
if (QmlJS::AST::UiObjectMember *member = it->member) {
|
|
|
|
const QmlJS::AST::SourceLocation loc = member->firstSourceLocation();
|
|
|
|
|
|
|
|
// insert a newline at the beginning of this binding
|
|
|
|
insert(position(loc), QLatin1String("\n"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// insert a newline before the closing brace
|
|
|
|
insert(position(_objectInitializer->rbraceToken), QLatin1String("\n"));
|
2010-06-14 14:52:43 +02:00
|
|
|
|
|
|
|
reindent(RefactoringChanges::Range(position(_objectInitializer->lbraceToken),
|
|
|
|
position(_objectInitializer->rbraceToken)));
|
|
|
|
|
2010-06-07 12:20:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual int check()
|
|
|
|
{
|
|
|
|
_objectInitializer = 0;
|
|
|
|
|
|
|
|
const int pos = textCursor().position();
|
|
|
|
|
|
|
|
if (QmlJS::AST::Node *member = semanticInfo().declaringMember(pos)) {
|
|
|
|
if (QmlJS::AST::UiObjectBinding *b = QmlJS::AST::cast<QmlJS::AST::UiObjectBinding *>(member)) {
|
2010-06-08 16:43:31 +02:00
|
|
|
if (b->initializer->lbraceToken.startLine == b->initializer->rbraceToken.startLine)
|
2010-06-07 12:20:07 +02:00
|
|
|
_objectInitializer = b->initializer;
|
|
|
|
|
|
|
|
} else if (QmlJS::AST::UiObjectDefinition *b = QmlJS::AST::cast<QmlJS::AST::UiObjectDefinition *>(member)) {
|
2010-06-08 16:43:31 +02:00
|
|
|
if (b->initializer->lbraceToken.startLine == b->initializer->rbraceToken.startLine)
|
2010-06-07 12:20:07 +02:00
|
|
|
_objectInitializer = b->initializer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-08 16:43:31 +02:00
|
|
|
if (! _objectInitializer)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0; // very high priority
|
2010-06-07 12:20:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
QmlJS::AST::UiObjectInitializer *_objectInitializer;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
} // end of anonymous namespace
|
2010-06-07 12:12:07 +02:00
|
|
|
|
|
|
|
|
2010-06-04 11:02:01 +02:00
|
|
|
QmlJSQuickFixOperation::QmlJSQuickFixOperation(TextEditor::BaseTextEditor *editor)
|
|
|
|
: TextEditor::QuickFixOperation(editor)
|
2010-06-14 14:52:43 +02:00
|
|
|
, _refactoringChanges(0)
|
2010-06-04 11:02:01 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
QmlJSQuickFixOperation::~QmlJSQuickFixOperation()
|
|
|
|
{
|
2010-06-14 14:52:43 +02:00
|
|
|
if (_refactoringChanges)
|
|
|
|
delete _refactoringChanges;
|
2010-06-04 11:02:01 +02:00
|
|
|
}
|
|
|
|
|
2010-06-07 12:12:07 +02:00
|
|
|
QmlJS::Document::Ptr QmlJSQuickFixOperation::document() const
|
|
|
|
{
|
|
|
|
return _semanticInfo.document;
|
|
|
|
}
|
|
|
|
|
|
|
|
const QmlJS::Snapshot &QmlJSQuickFixOperation::snapshot() const
|
|
|
|
{
|
|
|
|
return _semanticInfo.snapshot;
|
|
|
|
}
|
|
|
|
|
|
|
|
const SemanticInfo &QmlJSQuickFixOperation::semanticInfo() const
|
|
|
|
{
|
|
|
|
return _semanticInfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
int QmlJSQuickFixOperation::match(TextEditor::QuickFixState *state)
|
|
|
|
{
|
2010-06-14 14:52:43 +02:00
|
|
|
QmlJS::ModelManagerInterface *modelManager = ExtensionSystem::PluginManager::instance()->getObject<QmlJS::ModelManagerInterface>();
|
2010-06-07 12:12:07 +02:00
|
|
|
QmlJSQuickFixState *s = static_cast<QmlJSQuickFixState *>(state);
|
|
|
|
_semanticInfo = s->semanticInfo;
|
2010-06-14 14:52:43 +02:00
|
|
|
if (_refactoringChanges) {
|
|
|
|
delete _refactoringChanges;
|
|
|
|
}
|
|
|
|
_refactoringChanges = new QmlJSRefactoringChanges(modelManager, _semanticInfo.snapshot);
|
2010-06-07 12:12:07 +02:00
|
|
|
return check();
|
|
|
|
}
|
|
|
|
|
2010-06-14 14:52:43 +02:00
|
|
|
void QmlJSQuickFixOperation::apply()
|
|
|
|
{
|
|
|
|
_refactoringChanges->apply();
|
|
|
|
}
|
|
|
|
|
|
|
|
QmlJSRefactoringChanges *QmlJSQuickFixOperation::qmljsRefactoringChanges() const
|
|
|
|
{ return _refactoringChanges; }
|
|
|
|
|
|
|
|
RefactoringChanges *QmlJSQuickFixOperation::refactoringChanges() const
|
|
|
|
{ return qmljsRefactoringChanges(); }
|
|
|
|
|
2010-06-07 12:12:07 +02:00
|
|
|
unsigned QmlJSQuickFixOperation::position(const QmlJS::AST::SourceLocation &loc) const
|
|
|
|
{
|
|
|
|
return position(loc.startLine, loc.startColumn);
|
|
|
|
}
|
|
|
|
|
2010-06-04 11:02:01 +02:00
|
|
|
void QmlJSQuickFixOperation::move(const QmlJS::AST::SourceLocation &loc, int to)
|
|
|
|
{
|
|
|
|
move(position(loc.startColumn, loc.startColumn), to);
|
|
|
|
}
|
|
|
|
|
|
|
|
void QmlJSQuickFixOperation::replace(const QmlJS::AST::SourceLocation &loc, const QString &replacement)
|
|
|
|
{
|
|
|
|
replace(position(loc.startLine, loc.startColumn), replacement);
|
|
|
|
}
|
|
|
|
|
|
|
|
void QmlJSQuickFixOperation::remove(const QmlJS::AST::SourceLocation &loc)
|
|
|
|
{
|
|
|
|
remove(position(loc.startLine, loc.startColumn));
|
|
|
|
}
|
|
|
|
|
|
|
|
void QmlJSQuickFixOperation::copy(const QmlJS::AST::SourceLocation &loc, int to)
|
|
|
|
{
|
|
|
|
copy(position(loc.startLine, loc.startColumn), to);
|
|
|
|
}
|
|
|
|
|
2010-06-03 15:49:29 +02:00
|
|
|
QmlJSQuickFixCollector::QmlJSQuickFixCollector()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
QmlJSQuickFixCollector::~QmlJSQuickFixCollector()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-06-07 12:12:07 +02:00
|
|
|
bool QmlJSQuickFixCollector::supportsEditor(TextEditor::ITextEditable *editable)
|
|
|
|
{
|
|
|
|
if (qobject_cast<QmlJSTextEditor *>(editable->widget()) != 0)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-06-03 15:49:29 +02:00
|
|
|
TextEditor::QuickFixState *QmlJSQuickFixCollector::initializeCompletion(TextEditor::ITextEditable *editable)
|
|
|
|
{
|
|
|
|
if (QmlJSTextEditor *editor = qobject_cast<QmlJSTextEditor *>(editable->widget())) {
|
|
|
|
const SemanticInfo info = editor->semanticInfo();
|
|
|
|
|
|
|
|
if (editor->isOutdated()) {
|
|
|
|
// outdated
|
|
|
|
qWarning() << "TODO: outdated semantic info, force a reparse.";
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-06-07 12:12:07 +02:00
|
|
|
QmlJSQuickFixState *state = new QmlJSQuickFixState;
|
|
|
|
state->semanticInfo = info;
|
|
|
|
return state;
|
2010-06-03 15:49:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-06-07 12:12:07 +02:00
|
|
|
QList<TextEditor::QuickFixOperation::Ptr> QmlJSQuickFixCollector::quickFixOperations(TextEditor::BaseTextEditor *editor) const
|
2010-06-03 15:49:29 +02:00
|
|
|
{
|
|
|
|
QList<TextEditor::QuickFixOperation::Ptr> quickFixOperations;
|
2010-06-07 12:20:07 +02:00
|
|
|
quickFixOperations.append(TextEditor::QuickFixOperation::Ptr(new SplitInitializerOp(editor)));
|
2010-06-14 15:02:05 +02:00
|
|
|
quickFixOperations.append(TextEditor::QuickFixOperation::Ptr(new ComponentFromObjectDef(editor)));
|
2010-06-03 15:49:29 +02:00
|
|
|
return quickFixOperations;
|
|
|
|
}
|