Added infrastructure to change multiple files at once.

This commit is contained in:
Erik Verbruggen
2010-06-14 14:52:43 +02:00
parent b57a161101
commit 297b281ced
20 changed files with 638 additions and 84 deletions

View File

@@ -733,6 +733,11 @@ TokenCache *CPPEditor::tokenCache() const
return m_modelManager->tokenCache(editableInterface()); return m_modelManager->tokenCache(editableInterface());
} }
CppTools::CppModelManagerInterface *CPPEditor::modelManager() const
{
return m_modelManager;
}
void CPPEditor::startRename() void CPPEditor::startRename()
{ {
m_inRenameChanged = false; m_inRenameChanged = false;

View File

@@ -201,6 +201,8 @@ public:
CPlusPlus::TokenCache *tokenCache() const; CPlusPlus::TokenCache *tokenCache() const;
CppTools::CppModelManagerInterface *modelManager() const;
public Q_SLOTS: public Q_SLOTS:
virtual void setFontSettings(const TextEditor::FontSettings &); virtual void setFontSettings(const TextEditor::FontSettings &);
void setSortedMethodOverview(bool sort); void setSortedMethodOverview(bool sort);

View File

@@ -15,6 +15,7 @@ HEADERS += cppplugin.h \
cppeditor_global.h \ cppeditor_global.h \
cppclasswizard.h \ cppclasswizard.h \
cppquickfix.h cppquickfix.h
SOURCES += cppplugin.cpp \ SOURCES += cppplugin.cpp \
cppeditor.cpp \ cppeditor.cpp \
cpphighlighter.cpp \ cpphighlighter.cpp \
@@ -22,6 +23,7 @@ SOURCES += cppplugin.cpp \
cppfilewizard.cpp \ cppfilewizard.cpp \
cppclasswizard.cpp \ cppclasswizard.cpp \
cppquickfix.cpp cppquickfix.cpp
RESOURCES += cppeditor.qrc RESOURCES += cppeditor.qrc
OTHER_FILES += CppEditor.pluginspec CppEditor.mimetypes.xml OTHER_FILES += CppEditor.pluginspec CppEditor.mimetypes.xml

View File

@@ -47,6 +47,7 @@
#include <Name.h> #include <Name.h>
#include <Literals.h> #include <Literals.h>
#include <cpptools/cpprefactoringchanges.h>
#include <cpptools/cpptoolsconstants.h> #include <cpptools/cpptoolsconstants.h>
#include <cpptools/cppmodelmanagerinterface.h> #include <cpptools/cppmodelmanagerinterface.h>
@@ -864,28 +865,39 @@ private:
CppQuickFixOperation::CppQuickFixOperation(TextEditor::BaseTextEditor *editor) CppQuickFixOperation::CppQuickFixOperation(TextEditor::BaseTextEditor *editor)
: TextEditor::QuickFixOperation(editor), _topLevelNode(0) : TextEditor::QuickFixOperation(editor)
, _refactoringChanges(0)
, _topLevelNode(0)
{ } { }
CppQuickFixOperation::~CppQuickFixOperation() CppQuickFixOperation::~CppQuickFixOperation()
{ }
CppQuickFixOperation::Range CppQuickFixOperation::topLevelRange() const
{ {
if (topLevelNode()) if (_refactoringChanges)
return createRange(topLevelNode()); delete _refactoringChanges;
return Range();
} }
int CppQuickFixOperation::match(TextEditor::QuickFixState *state) int CppQuickFixOperation::match(TextEditor::QuickFixState *state)
{ {
CppQuickFixState *s = static_cast<CppQuickFixState *>(state); CppQuickFixState *s = static_cast<CppQuickFixState *>(state);
_document = s->info.doc; _document = s->info.doc;
_snapshot = s->info.snapshot; if (_refactoringChanges)
delete _refactoringChanges;
CPPEditor *cppEditor = qobject_cast<CPPEditor*>(editor());
_refactoringChanges = new CppTools::CppRefactoringChanges(s->info.snapshot, cppEditor->modelManager());
return match(s->path); return match(s->path);
} }
void CppQuickFixOperation::apply()
{
cppRefactoringChanges()->apply();
}
CppTools::CppRefactoringChanges *CppQuickFixOperation::cppRefactoringChanges() const
{ return _refactoringChanges; }
TextEditor::RefactoringChanges *CppQuickFixOperation::refactoringChanges() const
{ return cppRefactoringChanges(); }
CPlusPlus::AST *CppQuickFixOperation::topLevelNode() const CPlusPlus::AST *CppQuickFixOperation::topLevelNode() const
{ return _topLevelNode; } { return _topLevelNode; }
@@ -896,7 +908,9 @@ Document::Ptr CppQuickFixOperation::document() const
{ return _document; } { return _document; }
const Snapshot &CppQuickFixOperation::snapshot() const const Snapshot &CppQuickFixOperation::snapshot() const
{ return _snapshot; } {
return _refactoringChanges->snapshot();
}
const CPlusPlus::Token &CppQuickFixOperation::tokenAt(unsigned index) const const CPlusPlus::Token &CppQuickFixOperation::tokenAt(unsigned index) const
{ return _document->translationUnit()->tokenAt(index); } { return _document->translationUnit()->tokenAt(index); }
@@ -965,11 +979,6 @@ bool CppQuickFixOperation::isCursorOn(const CPlusPlus::AST *ast) const
return false; return false;
} }
CppQuickFixOperation::Range CppQuickFixOperation::createRange(AST *ast) const
{
return range(startOf(ast), endOf(ast));
}
void CppQuickFixOperation::move(unsigned tokenIndex, int to) void CppQuickFixOperation::move(unsigned tokenIndex, int to)
{ {
int start, end; int start, end;

View File

@@ -43,6 +43,7 @@
namespace CppTools { namespace CppTools {
class CppModelManagerInterface; class CppModelManagerInterface;
class CppRefactoringChanges;
} // end of namespace CppTools } // end of namespace CppTools
namespace CppEditor { namespace CppEditor {
@@ -61,10 +62,13 @@ public:
CPlusPlus::Document::Ptr document() const; CPlusPlus::Document::Ptr document() const;
const CPlusPlus::Snapshot &snapshot() const; const CPlusPlus::Snapshot &snapshot() const;
virtual Range topLevelRange() const;
virtual int match(TextEditor::QuickFixState *state); virtual int match(TextEditor::QuickFixState *state);
protected: protected:
virtual void apply();
virtual CppTools::CppRefactoringChanges *cppRefactoringChanges() const;
virtual TextEditor::RefactoringChanges *refactoringChanges() const;
CPlusPlus::AST *topLevelNode() const; CPlusPlus::AST *topLevelNode() const;
void setTopLevelNode(CPlusPlus::AST *topLevelNode); void setTopLevelNode(CPlusPlus::AST *topLevelNode);
@@ -100,11 +104,10 @@ protected:
void copy(const CPlusPlus::AST *ast, int to); void copy(const CPlusPlus::AST *ast, int to);
QString textOf(const CPlusPlus::AST *ast) const; QString textOf(const CPlusPlus::AST *ast) const;
Range createRange(CPlusPlus::AST *ast) const; // ### rename me
private: private:
CppTools::CppRefactoringChanges *_refactoringChanges;
CPlusPlus::Document::Ptr _document; CPlusPlus::Document::Ptr _document;
CPlusPlus::Snapshot _snapshot;
CPlusPlus::AST *_topLevelNode; CPlusPlus::AST *_topLevelNode;
}; };

View File

@@ -0,0 +1,75 @@
/**************************************************************************
**
** 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 "cpprefactoringchanges.h"
using namespace CPlusPlus;
using namespace CppTools;
using namespace TextEditor;
CppRefactoringChanges::CppRefactoringChanges(const Snapshot &snapshot,
CppModelManagerInterface *modelManager)
: m_snapshot(snapshot)
, m_modelManager(modelManager)
, m_workingCopy(modelManager->workingCopy())
{
Q_ASSERT(modelManager);
}
QStringList CppRefactoringChanges::apply()
{
const QStringList changedFiles = TextEditor::RefactoringChanges::apply();
m_modelManager->updateSourceFiles(changedFiles);
return changedFiles;
}
Document::Ptr CppRefactoringChanges::parsedDocumentForFile(const QString &fileName) const
{
Document::Ptr doc = m_snapshot.document(fileName);
QString source;
if (m_workingCopy.contains(fileName)) {
QPair<QString, unsigned> workingCopy = m_workingCopy.get(fileName);
if (doc && doc->editorRevision() == workingCopy.second)
return doc;
else
source = workingCopy.first;
} else {
QFile file(fileName);
if (! file.open(QFile::ReadOnly))
return Document::Ptr();
source = QTextStream(&file).readAll(); // ### FIXME read bytes, and remove the convert below
file.close();
}
doc = m_snapshot.documentFromSource(source.toLatin1(), fileName);
doc->check();
return doc;
}

View File

@@ -0,0 +1,62 @@
/**************************************************************************
**
** 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 CPPREFACTORINGCHANGES_H
#define CPPREFACTORINGCHANGES_H
#include <cplusplus/CppDocument.h>
#include <cpptools/cppmodelmanagerinterface.h>
#include <cpptools/cpptools_global.h>
#include <texteditor/refactoringchanges.h>
namespace CppTools {
class CPPTOOLS_EXPORT CppRefactoringChanges: public TextEditor::RefactoringChanges
{
public:
CppRefactoringChanges(const CPlusPlus::Snapshot &snapshot, CppModelManagerInterface *modelManager);
virtual QStringList apply();
const CPlusPlus::Snapshot &snapshot() const
{ return m_snapshot; }
CPlusPlus::Document::Ptr parsedDocumentForFile(const QString &fileName) const;
private:
CPlusPlus::Snapshot m_snapshot;
CppModelManagerInterface *m_modelManager;
CppModelManagerInterface::WorkingCopy m_workingCopy;
};
} // namespace CppTools
#endif // CPPREFACTORINGCHANGES_H

View File

@@ -23,7 +23,8 @@ HEADERS += completionsettingspage.h \
searchsymbols.h \ searchsymbols.h \
cppdoxygen.h \ cppdoxygen.h \
cppfilesettingspage.h \ cppfilesettingspage.h \
cppfindreferences.h cppfindreferences.h \
cpprefactoringchanges.h
SOURCES += completionsettingspage.cpp \ SOURCES += completionsettingspage.cpp \
cppclassesfilter.cpp \ cppclassesfilter.cpp \
@@ -38,7 +39,8 @@ SOURCES += completionsettingspage.cpp \
cppdoxygen.cpp \ cppdoxygen.cpp \
cppfilesettingspage.cpp \ cppfilesettingspage.cpp \
abstracteditorsupport.cpp \ abstracteditorsupport.cpp \
cppfindreferences.cpp cppfindreferences.cpp \
cpprefactoringchanges.cpp
FORMS += completionsettingspage.ui \ FORMS += completionsettingspage.ui \
cppfilesettingspage.ui cppfilesettingspage.ui

View File

@@ -436,7 +436,7 @@ protected:
range.ast = member; range.ast = member;
range.begin = QTextCursor(_textDocument); range.begin = QTextCursor(_textDocument);
range.begin.setPosition(ast->lbraceToken.begin()); range.begin.setPosition(member->firstSourceLocation().begin());
range.end = QTextCursor(_textDocument); range.end = QTextCursor(_textDocument);
range.end.setPosition(ast->rbraceToken.end()); range.end.setPosition(ast->rbraceToken.end());

View File

@@ -21,7 +21,8 @@ HEADERS += \
qmljshoverhandler.h \ qmljshoverhandler.h \
qmljsmodelmanager.h \ qmljsmodelmanager.h \
qmljspreviewrunner.h \ qmljspreviewrunner.h \
qmljsquickfix.h qmljsquickfix.h \
qmljsrefactoringchanges.h
SOURCES += \ SOURCES += \
qmljscodecompletion.cpp \ qmljscodecompletion.cpp \
@@ -35,7 +36,8 @@ SOURCES += \
qmljshoverhandler.cpp \ qmljshoverhandler.cpp \
qmljsmodelmanager.cpp \ qmljsmodelmanager.cpp \
qmljspreviewrunner.cpp \ qmljspreviewrunner.cpp \
qmljsquickfix.cpp qmljsquickfix.cpp \
qmljsrefactoringchanges.cpp
RESOURCES += qmljseditor.qrc RESOURCES += qmljseditor.qrc
OTHER_FILES += QmlJSEditor.pluginspec QmlJSEditor.mimetypes.xml OTHER_FILES += QmlJSEditor.pluginspec QmlJSEditor.mimetypes.xml

View File

@@ -29,11 +29,19 @@
#include "qmljsquickfix.h" #include "qmljsquickfix.h"
#include "qmljseditor.h" #include "qmljseditor.h"
#include "qmljsrefactoringchanges.h"
#include "qmljs/parser/qmljsast_p.h" #include "qmljs/parser/qmljsast_p.h"
#include <extensionsystem/pluginmanager.h>
#include <qmljs/qmljsmodelmanagerinterface.h>
#include <QtGui/QApplication> #include <QtGui/QApplication>
#include <QtCore/QDebug> #include <QtCore/QDebug>
using namespace QmlJSEditor;
using namespace QmlJSEditor::Internal; using namespace QmlJSEditor::Internal;
using TextEditor::RefactoringChanges;
class QmlJSQuickFixState: public TextEditor::QuickFixState class QmlJSQuickFixState: public TextEditor::QuickFixState
{ {
@@ -54,14 +62,6 @@ public:
return QApplication::translate("QmlJSEditor::QuickFix", "Split initializer"); return QApplication::translate("QmlJSEditor::QuickFix", "Split initializer");
} }
virtual Range topLevelRange() const
{
Q_ASSERT(_objectInitializer);
return range(position(_objectInitializer->lbraceToken),
position(_objectInitializer->rbraceToken));
}
virtual void createChangeSet() virtual void createChangeSet()
{ {
Q_ASSERT(_objectInitializer != 0); Q_ASSERT(_objectInitializer != 0);
@@ -77,6 +77,10 @@ public:
// insert a newline before the closing brace // insert a newline before the closing brace
insert(position(_objectInitializer->rbraceToken), QLatin1String("\n")); insert(position(_objectInitializer->rbraceToken), QLatin1String("\n"));
reindent(RefactoringChanges::Range(position(_objectInitializer->lbraceToken),
position(_objectInitializer->rbraceToken)));
} }
virtual int check() virtual int check()
@@ -112,11 +116,14 @@ private:
QmlJSQuickFixOperation::QmlJSQuickFixOperation(TextEditor::BaseTextEditor *editor) QmlJSQuickFixOperation::QmlJSQuickFixOperation(TextEditor::BaseTextEditor *editor)
: TextEditor::QuickFixOperation(editor) : TextEditor::QuickFixOperation(editor)
, _refactoringChanges(0)
{ {
} }
QmlJSQuickFixOperation::~QmlJSQuickFixOperation() QmlJSQuickFixOperation::~QmlJSQuickFixOperation()
{ {
if (_refactoringChanges)
delete _refactoringChanges;
} }
QmlJS::Document::Ptr QmlJSQuickFixOperation::document() const QmlJS::Document::Ptr QmlJSQuickFixOperation::document() const
@@ -136,11 +143,27 @@ const SemanticInfo &QmlJSQuickFixOperation::semanticInfo() const
int QmlJSQuickFixOperation::match(TextEditor::QuickFixState *state) int QmlJSQuickFixOperation::match(TextEditor::QuickFixState *state)
{ {
QmlJS::ModelManagerInterface *modelManager = ExtensionSystem::PluginManager::instance()->getObject<QmlJS::ModelManagerInterface>();
QmlJSQuickFixState *s = static_cast<QmlJSQuickFixState *>(state); QmlJSQuickFixState *s = static_cast<QmlJSQuickFixState *>(state);
_semanticInfo = s->semanticInfo; _semanticInfo = s->semanticInfo;
if (_refactoringChanges) {
delete _refactoringChanges;
}
_refactoringChanges = new QmlJSRefactoringChanges(modelManager, _semanticInfo.snapshot);
return check(); return check();
} }
void QmlJSQuickFixOperation::apply()
{
_refactoringChanges->apply();
}
QmlJSRefactoringChanges *QmlJSQuickFixOperation::qmljsRefactoringChanges() const
{ return _refactoringChanges; }
RefactoringChanges *QmlJSQuickFixOperation::refactoringChanges() const
{ return qmljsRefactoringChanges(); }
unsigned QmlJSQuickFixOperation::position(const QmlJS::AST::SourceLocation &loc) const unsigned QmlJSQuickFixOperation::position(const QmlJS::AST::SourceLocation &loc) const
{ {
return position(loc.startLine, loc.startColumn); return position(loc.startLine, loc.startColumn);

View File

@@ -31,6 +31,7 @@
#define QMLJSQUICKFIX_H #define QMLJSQUICKFIX_H
#include "qmljseditor.h" #include "qmljseditor.h"
#include <texteditor/quickfix.h> #include <texteditor/quickfix.h>
#include <qmljs/parser/qmljsastfwd_p.h> #include <qmljs/parser/qmljsastfwd_p.h>
#include <qmljs/qmljsdocument.h> #include <qmljs/qmljsdocument.h>
@@ -40,6 +41,7 @@ namespace QmlJS {
} }
namespace QmlJSEditor { namespace QmlJSEditor {
class QmlJSRefactoringChanges;
namespace Internal { namespace Internal {
@@ -69,6 +71,10 @@ protected:
using TextEditor::QuickFixOperation::charAt; using TextEditor::QuickFixOperation::charAt;
using TextEditor::QuickFixOperation::position; using TextEditor::QuickFixOperation::position;
virtual void apply();
QmlJSRefactoringChanges *qmljsRefactoringChanges() const;
virtual TextEditor::RefactoringChanges *refactoringChanges() const;
unsigned position(const QmlJS::AST::SourceLocation &loc) const; unsigned position(const QmlJS::AST::SourceLocation &loc) const;
// token based operations // token based operations
@@ -79,6 +85,7 @@ protected:
private: private:
SemanticInfo _semanticInfo; SemanticInfo _semanticInfo;
QmlJSRefactoringChanges *_refactoringChanges;
}; };
class QmlJSQuickFixCollector: public TextEditor::QuickFixCollector class QmlJSQuickFixCollector: public TextEditor::QuickFixCollector

View File

@@ -0,0 +1,50 @@
/**************************************************************************
**
** 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 "qmljsrefactoringchanges.h"
#include <qmljs/qmljsmodelmanagerinterface.h>
using namespace QmlJS;
using namespace QmlJSEditor;
QmlJSRefactoringChanges::QmlJSRefactoringChanges(ModelManagerInterface *modelManager,
const Snapshot &snapshot)
: m_modelManager(modelManager)
, m_snapshot(snapshot)
{
Q_ASSERT(modelManager);
}
QStringList QmlJSRefactoringChanges::apply()
{
const QStringList changedFiles = TextEditor::RefactoringChanges::apply();
m_modelManager->updateSourceFiles(changedFiles, true);
return changedFiles;
}

View File

@@ -0,0 +1,58 @@
/**************************************************************************
**
** 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 QMLREFACTORINGCHANGES_H
#define QMLREFACTORINGCHANGES_H
#include <qmljs/qmljsdocument.h>
#include <texteditor/refactoringchanges.h>
namespace QmlJS {
class ModelManagerInterface;
} // namespace QmlJS
namespace QmlJSEditor {
class QmlJSRefactoringChanges: public TextEditor::RefactoringChanges
{
public:
QmlJSRefactoringChanges(QmlJS::ModelManagerInterface *modelManager,
const QmlJS::Snapshot &snapshot);
virtual QStringList apply();
private:
QmlJS::ModelManagerInterface *m_modelManager;
QmlJS::Snapshot m_snapshot;
};
} // namespace QmlJSEditor
#endif // QMLREFACTORINGCHANGES_H

View File

@@ -69,6 +69,7 @@ public:
/* returns the list of unique files that were passed in items */ /* returns the list of unique files that were passed in items */
static QStringList replaceAll(const QString &txt, static QStringList replaceAll(const QString &txt,
const QList<Find::SearchResultItem> &items); const QList<Find::SearchResultItem> &items);
protected: protected:
virtual QStringList files() = 0; virtual QStringList files() = 0;
void writeCommonSettings(QSettings *settings); void writeCommonSettings(QSettings *settings);

View File

@@ -30,11 +30,14 @@
#include "quickfix.h" #include "quickfix.h"
#include "basetexteditor.h" #include "basetexteditor.h"
#include <coreplugin/ifile.h>
#include <QtGui/QApplication> #include <QtGui/QApplication>
#include <QtGui/QTextBlock> #include <QtGui/QTextBlock>
#include <QtCore/QDebug> #include <QtCore/QDebug>
using TextEditor::RefactoringChanges;
using TextEditor::QuickFixOperation; using TextEditor::QuickFixOperation;
using TextEditor::QuickFixCollector; using TextEditor::QuickFixCollector;
@@ -72,49 +75,16 @@ int QuickFixOperation::selectionEnd() const
return _textCursor.selectionEnd(); return _textCursor.selectionEnd();
} }
const Utils::ChangeSet &QuickFixOperation::changeSet() const
{
return _changeSet;
}
void QuickFixOperation::apply()
{
const Range r = topLevelRange();
_textCursor.beginEditBlock();
_changeSet.apply(&_textCursor);
reindent(r);
_textCursor.endEditBlock();
}
QuickFixOperation::Range QuickFixOperation::range(int from, int to) const
{
QTextDocument *doc = editor()->document();
QTextCursor begin(doc);
begin.setPosition(from);
QTextCursor end(doc);
end.setPosition(to);
Range range;
range.begin = begin;
range.end = end;
return range;
}
int QuickFixOperation::position(int line, int column) const int QuickFixOperation::position(int line, int column) const
{ {
QTextDocument *doc = editor()->document(); QTextDocument *doc = editor()->document();
return doc->findBlockByNumber(line - 1).position() + column - 1; return doc->findBlockByNumber(line - 1).position() + column - 1;
} }
void QuickFixOperation::reindent(const Range &range) void QuickFixOperation::reindent(const RefactoringChanges::Range &range)
{ {
if (! range.isNull()) { if (! range.isNull()) {
QTextCursor tc = range.begin; refactoringChanges()->reindent(editor()->file()->fileName(), range);
tc.setPosition(range.end.position(), QTextCursor::KeepAnchor);
editor()->indentInsertedText(tc);
} }
} }
@@ -162,9 +132,18 @@ QString QuickFixOperation::textOf(int start, int end) const
return tc.selectedText(); return tc.selectedText();
} }
TextEditor::RefactoringChanges::Range QuickFixOperation::range(int start, int end)
{
return TextEditor::RefactoringChanges::Range(start, end);
}
void QuickFixOperation::perform() void QuickFixOperation::perform()
{ {
createChangeSet(); createChangeSet();
if (!_changeSet.isEmpty())
refactoringChanges()->changeFile(editor()->file()->fileName(), _changeSet);
apply(); apply();
} }

View File

@@ -32,6 +32,8 @@
#include "texteditor_global.h" #include "texteditor_global.h"
#include "icompletioncollector.h" #include "icompletioncollector.h"
#include <texteditor/refactoringchanges.h>
#include <utils/changeset.h> #include <utils/changeset.h>
#include <QtCore/QSharedPointer> #include <QtCore/QSharedPointer>
@@ -58,41 +60,28 @@ class TEXTEDITOR_EXPORT QuickFixOperation
public: public:
typedef QSharedPointer<QuickFixOperation> Ptr; typedef QSharedPointer<QuickFixOperation> Ptr;
struct Range {
Range() {}
Range(const QTextCursor &tc): begin(tc), end(tc) {}
bool isNull() const { return begin.isNull() || end.isNull(); }
QTextCursor begin;
QTextCursor end;
};
public: public:
QuickFixOperation(TextEditor::BaseTextEditor *editor); QuickFixOperation(TextEditor::BaseTextEditor *editor);
virtual ~QuickFixOperation(); virtual ~QuickFixOperation();
virtual QString description() const = 0; virtual QString description() const = 0;
virtual void createChangeSet() = 0; virtual void createChangeSet() = 0;
virtual Range topLevelRange() const = 0;
virtual int match(QuickFixState *state) = 0; virtual int match(QuickFixState *state) = 0;
void perform(); void perform();
void apply();
TextEditor::BaseTextEditor *editor() const; TextEditor::BaseTextEditor *editor() const;
QTextCursor textCursor() const; QTextCursor textCursor() const;
void setTextCursor(const QTextCursor &cursor); void setTextCursor(const QTextCursor &cursor);
void reindent(const Range &range); void reindent(const TextEditor::RefactoringChanges::Range &range);
int selectionStart() const; int selectionStart() const;
int selectionEnd() const; int selectionEnd() const;
int position(int line, int column) const; int position(int line, int column) const;
Range range(int from, int to) const;
void move(int start, int end, int to); void move(int start, int end, int to);
void replace(int start, int end, const QString &replacement); void replace(int start, int end, const QString &replacement);
@@ -104,7 +93,11 @@ public:
QChar charAt(int offset) const; QChar charAt(int offset) const;
QString textOf(int start, int end) const; QString textOf(int start, int end) const;
const Utils::ChangeSet &changeSet() const; static TextEditor::RefactoringChanges::Range range(int start, int end);
protected:
virtual void apply() = 0;
virtual TextEditor::RefactoringChanges *refactoringChanges() const = 0;
private: private:
TextEditor::BaseTextEditor *_editor; TextEditor::BaseTextEditor *_editor;

View File

@@ -0,0 +1,191 @@
/**************************************************************************
**
** 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 "refactoringchanges.h"
#include <coreplugin/editormanager/editormanager.h>
#include <extensionsystem/pluginmanager.h>
#include <QtCore/QFile>
#include <QtCore/QSet>
#include <QtGui/QTextBlock>
using namespace TextEditor;
RefactoringChanges::~RefactoringChanges()
{}
void RefactoringChanges::createFile(const QString &fileName, const QString &contents)
{
m_contentsByCreatedFile.insert(fileName, contents);
}
void RefactoringChanges::changeFile(const QString &fileName, const Utils::ChangeSet &changeSet)
{
m_changesByFile.insert(fileName, changeSet);
}
void RefactoringChanges::reindent(const QString &fileName, const Range &range)
{
m_indentRangesByFile[fileName].append(range);
}
QStringList RefactoringChanges::apply()
{
QSet<QString> changed;
{ // create files
foreach (const QString &fileName, m_contentsByCreatedFile.keys()) {
BaseTextEditor *editor = editorForNewFile(fileName);
if (editor == 0)
continue;
QTextCursor tc = editor->textCursor();
tc.beginEditBlock();
tc.setPosition(0);
tc.insertText(m_contentsByCreatedFile.value(fileName));
foreach (const Range &range, m_indentRangesByFile.value(fileName, QList<Range>())) {
QTextCursor indentCursor = editor->textCursor();
indentCursor.setPosition(range.begin);
indentCursor.setPosition(range.end, QTextCursor::KeepAnchor);
editor->indentInsertedText(indentCursor);
}
tc.endEditBlock();
changed.insert(fileName);
}
}
{ // change and indent files
foreach (const QString &fileName, m_changesByFile.keys()) {
BaseTextEditor *editor = editorForFile(fileName, true);
if (editor == 0)
continue;
QTextCursor tc = editor->textCursor();
tc.beginEditBlock();
typedef QPair<QTextCursor, QTextCursor> CursorPair;
QList<CursorPair> cursorPairs;
foreach (const Range &range, m_indentRangesByFile.value(fileName, QList<Range>())) {
QTextCursor start = editor->textCursor();
QTextCursor end = editor->textCursor();
start.setPosition(range.begin);
end.setPosition(range.end);
cursorPairs.append(qMakePair(start, end));
}
QTextCursor changeSetCursor = editor->textCursor();
Utils::ChangeSet changeSet = m_changesByFile[fileName];
changeSet.apply(&changeSetCursor);
foreach (const CursorPair &cursorPair, cursorPairs) {
QTextCursor indentCursor = cursorPair.first;
indentCursor.setPosition(cursorPair.second.position(),
QTextCursor::KeepAnchor);
editor->indentInsertedText(indentCursor);
}
tc.endEditBlock();
changed.insert(fileName);
}
}
{ // Indent files which are not changed
foreach (const QString &fileName, m_indentRangesByFile.keys()) {
BaseTextEditor *editor = editorForFile(fileName);
if (editor == 0)
continue;
if (changed.contains(fileName))
continue;
QTextCursor tc = editor->textCursor();
tc.beginEditBlock();
foreach (const Range &range, m_indentRangesByFile.value(fileName, QList<Range>())) {
QTextCursor indentCursor = editor->textCursor();
indentCursor.setPosition(range.begin);
indentCursor.setPosition(range.end, QTextCursor::KeepAnchor);
editor->indentInsertedText(indentCursor);
}
tc.endEditBlock();
changed.insert(fileName);
}
}
{ // Delete files
// ###
}
return changed.toList();
}
int RefactoringChanges::positionInFile(const QString &fileName, int line, int column) const
{
if (BaseTextEditor *editor = editorForFile(fileName)) {
return editor->document()->findBlockByNumber(line).position() + column;
} else {
return -1;
}
}
BaseTextEditor *RefactoringChanges::editorForFile(const QString &fileName,
bool openIfClosed)
{
Core::EditorManager *editorManager = Core::EditorManager::instance();
const QList<Core::IEditor *> editors = editorManager->editorsForFileName(fileName);
foreach (Core::IEditor *editor, editors) {
BaseTextEditor *textEditor = qobject_cast<BaseTextEditor *>(editor->widget());
if (textEditor != 0)
return textEditor;
}
if (!openIfClosed)
return 0;
Core::IEditor *editor = editorManager->openEditor(fileName, QString(),
Core::EditorManager::NoActivate | Core::EditorManager::IgnoreNavigationHistory | Core::EditorManager::NoModeSwitch);
return qobject_cast<BaseTextEditor *>(editor->widget());
}
BaseTextEditor *RefactoringChanges::editorForNewFile(const QString &fileName)
{
QFile f(fileName);
if (f.exists())
return 0;
if (!f.open(QIODevice::Append))
return 0;
f.close();
return editorForFile(fileName, true);
}

View File

@@ -0,0 +1,89 @@
/**************************************************************************
**
** 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 REFACTORINGCHANGES_H
#define REFACTORINGCHANGES_H
#include <utils/changeset.h>
#include <texteditor/basetexteditor.h>
#include <texteditor/texteditor_global.h>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
namespace TextEditor {
class TEXTEDITOR_EXPORT RefactoringChanges
{
public:
struct Range {
Range()
: begin(0)
, end(0)
{}
Range(int beginPosition, int endPosition)
: begin(beginPosition)
, end(endPosition)
{}
bool isNull() const
{ return begin == 0 || end == 0; }
int begin;
int end;
};
public:
virtual ~RefactoringChanges();
void createFile(const QString &fileName, const QString &contents);
void changeFile(const QString &fileName, const Utils::ChangeSet &changeSet);
// TODO:
// void deleteFile(const QString &fileName);
void reindent(const QString &fileName, const Range &range);
virtual QStringList apply();
int positionInFile(const QString &fileName, int line, int column = 0) const;
static BaseTextEditor *editorForFile(const QString &fileName,
bool openIfClosed = false);
static BaseTextEditor *editorForNewFile(const QString &fileName);
private:
QMap<QString, QString> m_contentsByCreatedFile;
QMap<QString, Utils::ChangeSet> m_changesByFile;
QMap<QString, QList<Range> > m_indentRangesByFile;
};
} // namespace TextEditor
#endif // REFACTORINGCHANGES_H

View File

@@ -58,7 +58,8 @@ SOURCES += texteditorplugin.cpp \
generichighlighter/highlightersettings.cpp \ generichighlighter/highlightersettings.cpp \
generichighlighter/managedefinitionsdialog.cpp \ generichighlighter/managedefinitionsdialog.cpp \
generichighlighter/highlightdefinitionmetadata.cpp \ generichighlighter/highlightdefinitionmetadata.cpp \
generichighlighter/definitiondownloader.cpp generichighlighter/definitiondownloader.cpp \
refactoringchanges.cpp
HEADERS += texteditorplugin.h \ HEADERS += texteditorplugin.h \
textfilewizard.h \ textfilewizard.h \
@@ -119,8 +120,8 @@ HEADERS += texteditorplugin.h \
generichighlighter/highlightersettings.h \ generichighlighter/highlightersettings.h \
generichighlighter/managedefinitionsdialog.h \ generichighlighter/managedefinitionsdialog.h \
generichighlighter/highlightdefinitionmetadata.h \ generichighlighter/highlightdefinitionmetadata.h \
generichighlighter/definitiondownloader.h generichighlighter/definitiondownloader.h \
refactoringchanges.h
FORMS += behaviorsettingspage.ui \ FORMS += behaviorsettingspage.ui \
displaysettingspage.ui \ displaysettingspage.ui \