Commit 0355e37e authored by Christian Kamm's avatar Christian Kamm
Browse files

QuickFix: Migrate to a nicer API for cross-file quick fixes.

parent ca5076e5
......@@ -82,16 +82,14 @@ public:
"CppEditor::DeclFromDef").arg(type));
}
void perform()
void performChanges(TextEditor::RefactoringFile *, CppRefactoringChanges *refactoring)
{
CppRefactoringChanges *changes = refactoringChanges();
Document::Ptr targetDoc = changes->document(m_targetFileName);
Document::Ptr targetDoc = refactoring->document(m_targetFileName);
InsertionPointLocator locator(targetDoc);
const InsertionLocation loc = locator.methodDeclarationInClass(m_targetSymbol, m_xsSpec);
Q_ASSERT(loc.isValid());
TextEditor::RefactoringFile targetFile = changes->file(m_targetFileName);
TextEditor::RefactoringFile targetFile = refactoring->file(m_targetFileName);
int targetPosition1 = targetFile.position(loc.line(), loc.column());
int targetPosition2 = qMax(0, targetFile.position(loc.line(), 1) - 1);
......@@ -100,8 +98,7 @@ public:
targetFile.change(target);
targetFile.indent(Utils::ChangeSet::Range(targetPosition2, targetPosition1));
changes->setActiveEditor(m_targetFileName, targetPosition1);
changes->apply();
refactoring->activateEditor(m_targetFileName, targetPosition1);
}
private:
......
......@@ -184,12 +184,19 @@ const Token &CppQuickFixState::tokenAt(unsigned index) const
CppQuickFixOperation::CppQuickFixOperation(const CppQuickFixState &state, int priority)
: QuickFixOperation(priority)
, _state(state)
, _refactoringChanges(new CppRefactoringChanges(state.document(), state.snapshot()))
{}
CppQuickFixOperation::~CppQuickFixOperation()
{}
void CppQuickFixOperation::perform()
{
CppRefactoringChanges refactoring(_state.document(), _state.snapshot());
TextEditor::RefactoringFile current = refactoring.file(fileName());
performChanges(&current, &refactoring);
}
const CppQuickFixState &CppQuickFixOperation::state() const
{
return _state;
......@@ -198,9 +205,6 @@ const CppQuickFixState &CppQuickFixOperation::state() const
QString CppQuickFixOperation::fileName() const
{ return state().document()->fileName(); }
CppRefactoringChanges *CppQuickFixOperation::refactoringChanges() const
{ return _refactoringChanges.data(); }
CppQuickFixFactory::CppQuickFixFactory()
{
}
......
......@@ -107,10 +107,12 @@ public:
CppQuickFixOperation(const CppQuickFixState &state, int priority = -1);
virtual ~CppQuickFixOperation();
virtual void perform();
protected:
QString fileName() const;
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *refactoring) = 0;
CppRefactoringChanges *refactoringChanges() const;
QString fileName() const;
const CppQuickFixState &state() const;
......@@ -131,7 +133,6 @@ protected: // Utility functions forwarding to CppQuickFixState
private:
CppQuickFixState _state;
QScopedPointer<CppRefactoringChanges> _refactoringChanges;
};
class CPPEDITOR_EXPORT CppQuickFixFactory: public TextEditor::QuickFixFactory
......
......@@ -148,7 +148,7 @@ private:
return QApplication::translate("CppTools::QuickFix", "Rewrite Using %1").arg(replacement);
}
virtual void perform()
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *)
{
ChangeSet changes;
if (negation) {
......@@ -161,8 +161,7 @@ private:
changes.insert(state().endOf(binary), ")");
}
changes.replace(range(binary->binary_op_token), replacement);
refactoringChanges()->changeFile(fileName(), changes);
refactoringChanges()->apply();
currentFile->change(changes);
}
};
};
......@@ -244,7 +243,7 @@ private:
return QApplication::translate("CppTools::QuickFix", "Rewrite Using %1").arg(replacement);
}
virtual void perform()
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *)
{
ChangeSet changes;
......@@ -252,8 +251,7 @@ private:
if (! replacement.isEmpty())
changes.replace(range(binary->binary_op_token), replacement);
refactoringChanges()->changeFile(fileName(), changes);
refactoringChanges()->apply();
currentFile->change(changes);
}
private:
......@@ -323,7 +321,7 @@ private:
pattern = mk->BinaryExpression(left, right);
}
virtual void perform()
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *)
{
ChangeSet changes;
changes.replace(range(pattern->binary_op_token), QLatin1String("||"));
......@@ -334,9 +332,8 @@ private:
changes.insert(start, QLatin1String("!("));
changes.insert(end, QLatin1String(")"));
refactoringChanges()->changeFile(fileName(), changes);
refactoringChanges()->reindent(fileName(), range(pattern));
refactoringChanges()->apply();
currentFile->change(changes);
currentFile->indent(range(pattern));
}
};
......@@ -425,7 +422,7 @@ private:
"Split Declaration"));
}
virtual void perform()
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *)
{
ChangeSet changes;
......@@ -451,9 +448,8 @@ private:
prevDeclarator = declarator;
}
refactoringChanges()->changeFile(fileName(), changes);
refactoringChanges()->reindent(fileName(), range(declaration));
refactoringChanges()->apply();
currentFile->change(changes);
currentFile->indent(range(declaration));
}
private:
......@@ -509,7 +505,7 @@ private:
"Add Curly Braces"));
}
virtual void perform()
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *)
{
ChangeSet changes;
......@@ -519,9 +515,8 @@ private:
const int end = endOf(_statement->lastToken() - 1);
changes.insert(end, "\n}");
refactoringChanges()->changeFile(fileName(), changes);
refactoringChanges()->reindent(fileName(), range(start, end));
refactoringChanges()->apply();
currentFile->change(changes);
currentFile->indent(range(start, end));
}
private:
......@@ -581,7 +576,7 @@ private:
pattern = mk.IfStatement(condition);
}
virtual void perform()
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *)
{
ChangeSet changes;
......@@ -591,9 +586,8 @@ private:
changes.move(range(condition), insertPos);
changes.insert(insertPos, QLatin1String(";\n"));
refactoringChanges()->changeFile(fileName(), changes);
refactoringChanges()->reindent(fileName(), range(pattern));
refactoringChanges()->apply();
currentFile->change(changes);
currentFile->indent(range(pattern));
}
ASTMatcher matcher;
......@@ -664,7 +658,7 @@ private:
pattern = mk.WhileStatement(condition);
}
virtual void perform()
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *)
{
ChangeSet changes;
......@@ -677,9 +671,8 @@ private:
changes.copy(range(core), insertPos);
changes.insert(insertPos, QLatin1String(";\n"));
refactoringChanges()->changeFile(fileName(), changes);
refactoringChanges()->reindent(fileName(), range(pattern));
refactoringChanges()->apply();
currentFile->change(changes);
currentFile->indent(range(pattern));
}
ASTMatcher matcher;
......@@ -774,18 +767,17 @@ private:
"Split if Statement"));
}
virtual void perform()
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *)
{
const Token binaryToken = state().tokenAt(condition->binary_op_token);
if (binaryToken.is(T_AMPER_AMPER))
splitAndCondition();
splitAndCondition(currentFile);
else
splitOrCondition();
refactoringChanges()->apply();
splitOrCondition(currentFile);
}
void splitAndCondition()
void splitAndCondition(TextEditor::RefactoringFile *currentFile)
{
ChangeSet changes;
......@@ -798,11 +790,11 @@ private:
changes.remove(lExprEnd, startOf(condition->right_expression));
changes.insert(endOf(pattern), QLatin1String("\n}"));
refactoringChanges()->changeFile(fileName(), changes);
refactoringChanges()->reindent(fileName(), range(pattern));
currentFile->change(changes);
currentFile->indent(range(pattern));
}
void splitOrCondition()
void splitOrCondition(TextEditor::RefactoringFile *currentFile)
{
ChangeSet changes;
......@@ -826,8 +818,8 @@ private:
const int lExprEnd = endOf(condition->left_expression);
changes.remove(lExprEnd, startOf(condition->right_expression));
refactoringChanges()->changeFile(fileName(), changes);
refactoringChanges()->reindent(fileName(), range(pattern));
currentFile->change(changes);
currentFile->indent(range(pattern));
}
private:
......@@ -913,7 +905,7 @@ private:
"Enclose in QLatin1String(...)"));
}
virtual void perform()
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *)
{
ChangeSet changes;
......@@ -928,8 +920,7 @@ private:
changes.insert(endOf(literal), ")");
refactoringChanges()->changeFile(fileName(), changes);
refactoringChanges()->apply();
currentFile->change(changes);
}
private:
......@@ -1035,7 +1026,7 @@ private:
setDescription(QApplication::translate("CppTools::QuickFix", "Mark as translateable"));
}
virtual void perform()
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *)
{
ChangeSet changes;
......@@ -1052,8 +1043,7 @@ private:
changes.insert(startPos, replacement);
changes.insert(endOf(m_literal), QLatin1String(")"));
refactoringChanges()->changeFile(fileName(), changes);
refactoringChanges()->apply();
currentFile->change(changes);
}
private:
......@@ -1117,7 +1107,7 @@ private:
"Convert to Objective-C String Literal"));
}
virtual void perform()
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *)
{
ChangeSet changes;
......@@ -1128,8 +1118,7 @@ private:
changes.insert(startOf(stringLiteral), "@");
}
refactoringChanges()->changeFile(fileName(), changes);
refactoringChanges()->apply();
currentFile->change(changes);
}
private:
......@@ -1266,12 +1255,11 @@ private:
, replacement(replacement)
{}
virtual void perform()
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *)
{
ChangeSet changes;
changes.replace(start, end, replacement);
refactoringChanges()->changeFile(fileName(), changes);
refactoringChanges()->apply();
currentFile->change(changes);
}
protected:
......@@ -1421,16 +1409,15 @@ private:
}
virtual void perform()
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *)
{
ChangeSet changes;
int start = endOf(compoundStatement->lbrace_token);
changes.insert(start, QLatin1String("\ncase ")
+ values.join(QLatin1String(":\nbreak;\ncase "))
+ QLatin1String(":\nbreak;"));
refactoringChanges()->changeFile(fileName(), changes);
refactoringChanges()->reindent(fileName(), range(compoundStatement));
refactoringChanges()->apply();
currentFile->change(changes);
currentFile->indent(range(compoundStatement));
}
CompoundStatementAST *compoundStatement;
......@@ -1498,7 +1485,7 @@ private:
"#include header file"));
}
virtual void perform()
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *)
{
Q_ASSERT(fwdClass != 0);
......@@ -1555,9 +1542,8 @@ private:
Utils::ChangeSet changes;
changes.insert(pos, QString("#include <%1>\n").arg(QFileInfo(best).fileName()));
refactoringChanges()->changeFile(fileName(), changes);
currentFile->change(changes);
}
refactoringChanges()->apply();
}
private:
......@@ -1613,7 +1599,7 @@ private:
setDescription(QApplication::translate("CppTools::QuickFix", "Add local declaration"));
}
virtual void perform()
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *)
{
TypeOfExpression typeOfExpression;
typeOfExpression.init(state().document(), state().snapshot(), state().context().bindings());
......@@ -1642,10 +1628,9 @@ private:
Utils::ChangeSet changes;
changes.insert(startOf(binaryAST), ty);
refactoringChanges()->changeFile(fileName(), changes);
currentFile->change(changes);
}
}
refactoringChanges()->apply();
}
private:
......@@ -1702,7 +1687,7 @@ private:
"Convert to Camel Case ..."));
}
virtual void perform()
virtual void performChanges(TextEditor::RefactoringFile *, CppRefactoringChanges *)
{
for (int i = 1; i < m_name.length(); ++i) {
QCharRef c = m_name[i];
......@@ -1715,7 +1700,6 @@ private:
}
}
static_cast<CppEditor::Internal::CPPEditor*>(state().editor())->renameUsagesNow(m_name);
refactoringChanges()->apply();
}
static bool isConvertibleUnderscore(const QString &name, int pos)
......
......@@ -63,13 +63,6 @@ const LookupContext &CppRefactoringChanges::context() const
return m_context;
}
QStringList CppRefactoringChanges::apply()
{
const QStringList changedFiles = TextEditor::RefactoringChanges::apply();
m_modelManager->updateSourceFiles(changedFiles);
return changedFiles;
}
Document::Ptr CppRefactoringChanges::document(const QString &fileName) const
{
QString source;
......@@ -120,3 +113,8 @@ void CppRefactoringChanges::indentSelection(const QTextCursor &selection) const
block = block.next();
} while (block.isValid() && block != end);
}
void CppRefactoringChanges::fileChanged(const QString &fileName)
{
m_modelManager->updateSourceFiles(QStringList(fileName));
}
......@@ -46,8 +46,6 @@ public:
CppRefactoringChanges(const CPlusPlus::Document::Ptr &thisDocument,
const CPlusPlus::Snapshot &snapshot);
virtual QStringList apply();
CPlusPlus::Document::Ptr thisDocument() const;
const CPlusPlus::Snapshot &snapshot() const;
CPlusPlus::Document::Ptr document(const QString &fileName) const;
......@@ -55,6 +53,7 @@ public:
private:
virtual void indentSelection(const QTextCursor &selection) const;
virtual void fileChanged(const QString &fileName);
private:
CPlusPlus::Document::Ptr m_thisDocument;
......
......@@ -92,7 +92,7 @@ public:
"Move Component into '%1.qml'").arg(m_componentName));
}
virtual void perform()
virtual void performChanges(TextEditor::RefactoringFile *currentFile, QmlJSRefactoringChanges *refactoring)
{
const QString newFileName = QFileInfo(fileName()).path()
+ QDir::separator() + m_componentName + QLatin1String(".qml");
......@@ -110,14 +110,15 @@ public:
const QString txt = imports + state().textOf(start, end)
+ QLatin1String("}\n");
// stop if we can't create the new file
if (!refactoring->createFile(newFileName, txt))
return;
Utils::ChangeSet changes;
changes.replace(start, end, m_componentName + QLatin1String(" {\n"));
refactoringChanges()->changeFile(fileName(), changes);
refactoringChanges()->reindent(fileName(), range(start, end + 1));
currentFile->change(changes);
currentFile->indent(range(start, end + 1));
refactoringChanges()->createFile(newFileName, txt);
refactoringChanges()->reindent(newFileName, range(0, txt.length() - 1));
refactoringChanges()->apply();
}
};
......
......@@ -75,8 +75,6 @@ unsigned QmlJSQuickFixState::startPosition(const QmlJS::AST::SourceLocation &loc
QmlJSQuickFixOperation::QmlJSQuickFixOperation(const QmlJSQuickFixState &state, int priority)
: QuickFixOperation(priority)
, _state(state)
, _refactoringChanges(new QmlJSRefactoringChanges(ExtensionSystem::PluginManager::instance()->getObject<QmlJS::ModelManagerInterface>(),
state.snapshot()))
{
}
......@@ -84,6 +82,15 @@ QmlJSQuickFixOperation::~QmlJSQuickFixOperation()
{
}
void QmlJSQuickFixOperation::perform()
{
QmlJSRefactoringChanges refactoring(ExtensionSystem::PluginManager::instance()->getObject<QmlJS::ModelManagerInterface>(),
_state.snapshot());
TextEditor::RefactoringFile current = refactoring.file(fileName());
performChanges(&current, &refactoring);
}
const QmlJSQuickFixState &QmlJSQuickFixOperation::state() const
{
return _state;
......@@ -94,11 +101,6 @@ QString QmlJSQuickFixOperation::fileName() const
return state().document()->fileName();
}
QmlJSRefactoringChanges *QmlJSQuickFixOperation::refactoringChanges() const
{
return _refactoringChanges.data();
}
QmlJSQuickFixFactory::QmlJSQuickFixFactory()
{
}
......
......@@ -105,16 +105,17 @@ public:
QmlJSQuickFixOperation(const QmlJSQuickFixState &state, int priority = -1);
virtual ~QmlJSQuickFixOperation();
virtual void perform();
protected:
virtual void performChanges(TextEditor::RefactoringFile *currentFile, QmlJSRefactoringChanges *refactoring) = 0;
/// \returns A const-reference to the state of the operation.
const QmlJSQuickFixState &state() const;
/// \returns The name of the file for for which this operation is invoked.
QString fileName() const;
/// \returns The refactoring changes associated with this quick-fix operation.
QmlJSRefactoringChanges *refactoringChanges() const;
protected: // Utility functions forwarding to QmlJSQuickFixState
/// \see QmlJSQuickFixState#startPosition
unsigned startPosition(const QmlJS::AST::SourceLocation &loc) const
......@@ -126,7 +127,6 @@ protected: // Utility functions forwarding to QmlJSQuickFixState
private:
QmlJSQuickFixState _state;
QScopedPointer<QmlJSRefactoringChanges> _refactoringChanges;
};
class QmlJSQuickFixFactory: public TextEditor::QuickFixFactory
......
......@@ -88,7 +88,7 @@ private:
"Split initializer"));
}
virtual void perform()
virtual void performChanges(TextEditor::RefactoringFile *currentFile, QmlJSRefactoringChanges *)
{
Q_ASSERT(_objectInitializer != 0);
......@@ -107,12 +107,9 @@ private:
changes.insert(startPosition(_objectInitializer->rbraceToken),
QLatin1String("\n"));
RefactoringFile file = refactoringChanges()->file(fileName());
file.change(changes);
file.indent(range(startPosition(_objectInitializer->lbraceToken),
startPosition(_objectInitializer->rbraceToken)));
refactoringChanges()->apply();
currentFile->change(changes);
currentFile->indent(range(startPosition(_objectInitializer->lbraceToken),
startPosition(_objectInitializer->rbraceToken)));
}
};
};
......
......@@ -34,7 +34,6 @@
#include <texteditor/texteditorsettings.h>
#include <texteditor/tabsettings.h>
using namespace QmlJS;
using namespace QmlJSEditor;
......@@ -46,13 +45,6 @@ QmlJSRefactoringChanges::QmlJSRefactoringChanges(ModelManagerInterface *modelMan
Q_ASSERT(modelManager);
}
QStringList QmlJSRefactoringChanges::apply()
{
const QStringList changedFiles = TextEditor::RefactoringChanges::apply();
m_modelManager->updateSourceFiles(changedFiles, true);
return changedFiles;
}
void QmlJSRefactoringChanges::indentSelection(const QTextCursor &selection) const
{
// ### shares code with QmlJSTextEditor::indent
......@@ -71,3 +63,8 @@ void QmlJSRefactoringChanges::indentSelection(const QTextCursor &selection) cons
block = block.next();
} while (block.isValid() && block != end);
}
void QmlJSRefactoringChanges::fileChanged(const QString &fileName)
{