Commit bbe64796 authored by Christian Kamm's avatar Christian Kamm

QuickFix: Introduce CppRefactoringFile.

parent 6c76866b
...@@ -82,10 +82,10 @@ public: ...@@ -82,10 +82,10 @@ public:
"CppEditor::DeclFromDef").arg(type)); "CppEditor::DeclFromDef").arg(type));
} }
void performChanges(TextEditor::RefactoringFile *, CppRefactoringChanges *refactoring) void performChanges(CppRefactoringFile *, CppRefactoringChanges *refactoring)
{ {
TextEditor::RefactoringFile targetFile = refactoring->file(m_targetFileName); CppRefactoringFile targetFile = refactoring->file(m_targetFileName);
Document::Ptr targetDoc = refactoring->document(targetFile); Document::Ptr targetDoc = targetFile.cppDocument();
InsertionPointLocator locator(targetDoc); InsertionPointLocator locator(targetDoc);
const InsertionLocation loc = locator.methodDeclarationInClass(m_targetSymbol, m_xsSpec); const InsertionLocation loc = locator.methodDeclarationInClass(m_targetSymbol, m_xsSpec);
Q_ASSERT(loc.isValid()); Q_ASSERT(loc.isValid());
......
...@@ -192,7 +192,7 @@ CppQuickFixOperation::~CppQuickFixOperation() ...@@ -192,7 +192,7 @@ CppQuickFixOperation::~CppQuickFixOperation()
void CppQuickFixOperation::perform() void CppQuickFixOperation::perform()
{ {
CppRefactoringChanges refactoring(_state.document(), _state.snapshot()); CppRefactoringChanges refactoring(_state.document(), _state.snapshot());
TextEditor::RefactoringFile current = refactoring.file(fileName()); CppRefactoringFile current = refactoring.file(fileName());
performChanges(&current, &refactoring); performChanges(&current, &refactoring);
} }
......
...@@ -110,7 +110,7 @@ public: ...@@ -110,7 +110,7 @@ public:
virtual void perform(); virtual void perform();
protected: protected:
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *refactoring) = 0; virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *refactoring) = 0;
QString fileName() const; QString fileName() const;
......
...@@ -148,7 +148,7 @@ private: ...@@ -148,7 +148,7 @@ private:
return QApplication::translate("CppTools::QuickFix", "Rewrite Using %1").arg(replacement); return QApplication::translate("CppTools::QuickFix", "Rewrite Using %1").arg(replacement);
} }
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *) virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *)
{ {
ChangeSet changes; ChangeSet changes;
if (negation) { if (negation) {
...@@ -243,7 +243,7 @@ private: ...@@ -243,7 +243,7 @@ private:
return QApplication::translate("CppTools::QuickFix", "Rewrite Using %1").arg(replacement); return QApplication::translate("CppTools::QuickFix", "Rewrite Using %1").arg(replacement);
} }
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *) virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *)
{ {
ChangeSet changes; ChangeSet changes;
...@@ -321,7 +321,7 @@ private: ...@@ -321,7 +321,7 @@ private:
pattern = mk->BinaryExpression(left, right); pattern = mk->BinaryExpression(left, right);
} }
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *) virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *)
{ {
ChangeSet changes; ChangeSet changes;
changes.replace(range(pattern->binary_op_token), QLatin1String("||")); changes.replace(range(pattern->binary_op_token), QLatin1String("||"));
...@@ -422,7 +422,7 @@ private: ...@@ -422,7 +422,7 @@ private:
"Split Declaration")); "Split Declaration"));
} }
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *) virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *)
{ {
ChangeSet changes; ChangeSet changes;
...@@ -505,7 +505,7 @@ private: ...@@ -505,7 +505,7 @@ private:
"Add Curly Braces")); "Add Curly Braces"));
} }
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *) virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *)
{ {
ChangeSet changes; ChangeSet changes;
...@@ -576,7 +576,7 @@ private: ...@@ -576,7 +576,7 @@ private:
pattern = mk.IfStatement(condition); pattern = mk.IfStatement(condition);
} }
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *) virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *)
{ {
ChangeSet changes; ChangeSet changes;
...@@ -658,7 +658,7 @@ private: ...@@ -658,7 +658,7 @@ private:
pattern = mk.WhileStatement(condition); pattern = mk.WhileStatement(condition);
} }
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *) virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *)
{ {
ChangeSet changes; ChangeSet changes;
...@@ -767,7 +767,7 @@ private: ...@@ -767,7 +767,7 @@ private:
"Split if Statement")); "Split if Statement"));
} }
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *) virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *)
{ {
const Token binaryToken = state().tokenAt(condition->binary_op_token); const Token binaryToken = state().tokenAt(condition->binary_op_token);
...@@ -777,7 +777,7 @@ private: ...@@ -777,7 +777,7 @@ private:
splitOrCondition(currentFile); splitOrCondition(currentFile);
} }
void splitAndCondition(TextEditor::RefactoringFile *currentFile) void splitAndCondition(CppRefactoringFile *currentFile)
{ {
ChangeSet changes; ChangeSet changes;
...@@ -794,7 +794,7 @@ private: ...@@ -794,7 +794,7 @@ private:
currentFile->indent(range(pattern)); currentFile->indent(range(pattern));
} }
void splitOrCondition(TextEditor::RefactoringFile *currentFile) void splitOrCondition(CppRefactoringFile *currentFile)
{ {
ChangeSet changes; ChangeSet changes;
...@@ -905,7 +905,7 @@ private: ...@@ -905,7 +905,7 @@ private:
"Enclose in QLatin1String(...)")); "Enclose in QLatin1String(...)"));
} }
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *) virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *)
{ {
ChangeSet changes; ChangeSet changes;
...@@ -1026,7 +1026,7 @@ private: ...@@ -1026,7 +1026,7 @@ private:
setDescription(QApplication::translate("CppTools::QuickFix", "Mark as translateable")); setDescription(QApplication::translate("CppTools::QuickFix", "Mark as translateable"));
} }
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *) virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *)
{ {
ChangeSet changes; ChangeSet changes;
...@@ -1107,7 +1107,7 @@ private: ...@@ -1107,7 +1107,7 @@ private:
"Convert to Objective-C String Literal")); "Convert to Objective-C String Literal"));
} }
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *) virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *)
{ {
ChangeSet changes; ChangeSet changes;
...@@ -1255,7 +1255,7 @@ private: ...@@ -1255,7 +1255,7 @@ private:
, replacement(replacement) , replacement(replacement)
{} {}
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *) virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *)
{ {
ChangeSet changes; ChangeSet changes;
changes.replace(start, end, replacement); changes.replace(start, end, replacement);
...@@ -1409,7 +1409,7 @@ private: ...@@ -1409,7 +1409,7 @@ private:
} }
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *) virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *)
{ {
ChangeSet changes; ChangeSet changes;
int start = endOf(compoundStatement->lbrace_token); int start = endOf(compoundStatement->lbrace_token);
...@@ -1485,7 +1485,7 @@ private: ...@@ -1485,7 +1485,7 @@ private:
"#include header file")); "#include header file"));
} }
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *) virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *)
{ {
Q_ASSERT(fwdClass != 0); Q_ASSERT(fwdClass != 0);
...@@ -1599,7 +1599,7 @@ private: ...@@ -1599,7 +1599,7 @@ private:
setDescription(QApplication::translate("CppTools::QuickFix", "Add local declaration")); setDescription(QApplication::translate("CppTools::QuickFix", "Add local declaration"));
} }
virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *) virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *)
{ {
TypeOfExpression typeOfExpression; TypeOfExpression typeOfExpression;
typeOfExpression.init(state().document(), state().snapshot(), state().context().bindings()); typeOfExpression.init(state().document(), state().snapshot(), state().context().bindings());
...@@ -1687,7 +1687,7 @@ private: ...@@ -1687,7 +1687,7 @@ private:
"Convert to Camel Case ...")); "Convert to Camel Case ..."));
} }
virtual void performChanges(TextEditor::RefactoringFile *, CppRefactoringChanges *) virtual void performChanges(CppRefactoringFile *, CppRefactoringChanges *)
{ {
for (int i = 1; i < m_name.length(); ++i) { for (int i = 1; i < m_name.length(); ++i) {
QCharRef c = m_name[i]; QCharRef c = m_name[i];
......
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
#include "cpprefactoringchanges.h" #include "cpprefactoringchanges.h"
#include <TranslationUnit.h>
#include <AST.h>
#include <cpptools/cppcodeformatter.h> #include <cpptools/cppcodeformatter.h>
#include <texteditor/texteditorsettings.h> #include <texteditor/texteditorsettings.h>
#include <texteditor/tabsettings.h> #include <texteditor/tabsettings.h>
...@@ -37,6 +39,7 @@ ...@@ -37,6 +39,7 @@
using namespace CppEditor; using namespace CppEditor;
using namespace CPlusPlus; using namespace CPlusPlus;
using namespace Utils;
CppRefactoringChanges::CppRefactoringChanges(const Document::Ptr &thisDocument, const Snapshot &snapshot) CppRefactoringChanges::CppRefactoringChanges(const Document::Ptr &thisDocument, const Snapshot &snapshot)
: m_thisDocument(thisDocument) : m_thisDocument(thisDocument)
...@@ -63,16 +66,9 @@ const LookupContext &CppRefactoringChanges::context() const ...@@ -63,16 +66,9 @@ const LookupContext &CppRefactoringChanges::context() const
return m_context; return m_context;
} }
Document::Ptr CppRefactoringChanges::document(const TextEditor::RefactoringFile &file) const CppRefactoringFile CppRefactoringChanges::file(const QString &fileName)
{ {
QString source = file.document()->toPlainText(); return CppRefactoringFile(fileName, this);
QString fileName = file.fileName();
const QByteArray contents = m_snapshot.preprocessedCode(source, fileName);
Document::Ptr doc = m_snapshot.documentFromSource(contents, fileName);
doc->check();
return doc;
} }
void CppRefactoringChanges::indentSelection(const QTextCursor &selection) const void CppRefactoringChanges::indentSelection(const QTextCursor &selection) const
...@@ -98,3 +94,126 @@ void CppRefactoringChanges::fileChanged(const QString &fileName) ...@@ -98,3 +94,126 @@ void CppRefactoringChanges::fileChanged(const QString &fileName)
{ {
m_modelManager->updateSourceFiles(QStringList(fileName)); m_modelManager->updateSourceFiles(QStringList(fileName));
} }
CppRefactoringFile::CppRefactoringFile()
{ }
CppRefactoringFile::CppRefactoringFile(const QString &fileName, CppRefactoringChanges *refactoringChanges)
: RefactoringFile(fileName, refactoringChanges)
{ }
Document::Ptr CppRefactoringFile::cppDocument() const
{
if (!m_cppDocument) {
const QString source = document()->toPlainText();
const QString name = fileName();
const Snapshot &snapshot = refactoringChanges()->snapshot();
const QByteArray contents = snapshot.preprocessedCode(source, name);
m_cppDocument = snapshot.documentFromSource(contents, name);
m_cppDocument->check();
}
return m_cppDocument;
}
Scope *CppRefactoringFile::scopeAt(unsigned index) const
{
unsigned line, column;
cppDocument()->translationUnit()->getTokenStartPosition(index, &line, &column);
return cppDocument()->scopeAt(line, column);
}
bool CppRefactoringFile::isCursorOn(unsigned tokenIndex) const
{
QTextCursor tc = cursor();
int cursorBegin = tc.selectionStart();
int start = startOf(tokenIndex);
int end = endOf(tokenIndex);
if (cursorBegin >= start && cursorBegin <= end)
return true;
return false;
}
bool CppRefactoringFile::isCursorOn(const AST *ast) const
{
QTextCursor tc = cursor();
int cursorBegin = tc.selectionStart();
int start = startOf(ast);
int end = endOf(ast);
if (cursorBegin >= start && cursorBegin <= end)
return true;
return false;
}
ChangeSet::Range CppRefactoringFile::range(unsigned tokenIndex) const
{
const Token &token = tokenAt(tokenIndex);
unsigned line, column;
cppDocument()->translationUnit()->getPosition(token.begin(), &line, &column);
const int start = document()->findBlockByNumber(line - 1).position() + column - 1;
return ChangeSet::Range(start, start + token.length());
}
ChangeSet::Range CppRefactoringFile::range(AST *ast) const
{
return ChangeSet::Range(startOf(ast), endOf(ast));
}
int CppRefactoringFile::startOf(unsigned index) const
{
unsigned line, column;
cppDocument()->translationUnit()->getPosition(tokenAt(index).begin(), &line, &column);
return document()->findBlockByNumber(line - 1).position() + column - 1;
}
int CppRefactoringFile::startOf(const AST *ast) const
{
return startOf(ast->firstToken());
}
int CppRefactoringFile::endOf(unsigned index) const
{
unsigned line, column;
cppDocument()->translationUnit()->getPosition(tokenAt(index).end(), &line, &column);
return document()->findBlockByNumber(line - 1).position() + column - 1;
}
int CppRefactoringFile::endOf(const AST *ast) const
{
if (unsigned end = ast->lastToken())
return endOf(end - 1);
else
return 0;
}
void CppRefactoringFile::startAndEndOf(unsigned index, int *start, int *end) const
{
unsigned line, column;
Token token(tokenAt(index));
cppDocument()->translationUnit()->getPosition(token.begin(), &line, &column);
*start = document()->findBlockByNumber(line - 1).position() + column - 1;
*end = *start + token.length();
}
QString CppRefactoringFile::textOf(const AST *ast) const
{
return textOf(startOf(ast), endOf(ast));
}
const Token &CppRefactoringFile::tokenAt(unsigned index) const
{
return cppDocument()->translationUnit()->tokenAt(index);
}
CppRefactoringChanges *CppRefactoringFile::refactoringChanges() const
{
return static_cast<CppRefactoringChanges *>(m_refactoringChanges);
}
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#ifndef CPPREFACTORINGCHANGES_H #ifndef CPPREFACTORINGCHANGES_H
#define CPPREFACTORINGCHANGES_H #define CPPREFACTORINGCHANGES_H
#include <ASTfwd.h>
#include <cplusplus/CppDocument.h> #include <cplusplus/CppDocument.h>
#include <cplusplus/LookupContext.h> #include <cplusplus/LookupContext.h>
...@@ -40,6 +41,43 @@ ...@@ -40,6 +41,43 @@
namespace CppEditor { namespace CppEditor {
class CppRefactoringChanges;
class CPPEDITOR_EXPORT CppRefactoringFile: public TextEditor::RefactoringFile
{
public:
CppRefactoringFile();
CppRefactoringFile(const QString &fileName, CppRefactoringChanges *refactoringChanges);
CPlusPlus::Document::Ptr cppDocument() const;
CPlusPlus::Scope *scopeAt(unsigned index) const;
bool isCursorOn(unsigned tokenIndex) const;
bool isCursorOn(const CPlusPlus::AST *ast) const;
Range range(int start, int end) const;
Range range(unsigned tokenIndex) const;
Range range(CPlusPlus::AST *ast) const;
const CPlusPlus::Token &tokenAt(unsigned index) const;
int startOf(unsigned index) const;
int startOf(const CPlusPlus::AST *ast) const;
int endOf(unsigned index) const;
int endOf(const CPlusPlus::AST *ast) const;
void startAndEndOf(unsigned index, int *start, int *end) const;
using TextEditor::RefactoringFile::textOf;
QString textOf(const CPlusPlus::AST *ast) const;
private:
CppRefactoringChanges *refactoringChanges() const;
mutable CPlusPlus::Document::Ptr m_cppDocument;
};
class CPPEDITOR_EXPORT CppRefactoringChanges: public TextEditor::RefactoringChanges class CPPEDITOR_EXPORT CppRefactoringChanges: public TextEditor::RefactoringChanges
{ {
public: public:
...@@ -50,7 +88,7 @@ public: ...@@ -50,7 +88,7 @@ public:
const CPlusPlus::Snapshot &snapshot() const; const CPlusPlus::Snapshot &snapshot() const;
const CPlusPlus::LookupContext &context() const; const CPlusPlus::LookupContext &context() const;
CPlusPlus::Document::Ptr document(const TextEditor::RefactoringFile &file) const; CppRefactoringFile file(const QString &fileName);
private: private:
virtual void indentSelection(const QTextCursor &selection) const; virtual void indentSelection(const QTextCursor &selection) const;
......
...@@ -196,11 +196,11 @@ RefactoringFile::RefactoringFile(const RefactoringFile &other) ...@@ -196,11 +196,11 @@ RefactoringFile::RefactoringFile(const RefactoringFile &other)
RefactoringFile::~RefactoringFile() RefactoringFile::~RefactoringFile()
{ {
if (m_openEditor) if (m_refactoringChanges && m_openEditor)
m_editor = m_refactoringChanges->openEditor(m_fileName, -1); m_editor = m_refactoringChanges->openEditor(m_fileName, -1);
// apply changes, if any // apply changes, if any
if (!m_indentRanges.isEmpty() || !m_changes.isEmpty()) { if (m_refactoringChanges && !(m_indentRanges.isEmpty() && m_changes.isEmpty())) {
QTextDocument *doc = mutableDocument(); QTextDocument *doc = mutableDocument();
{ {
QTextCursor c = cursor(); QTextCursor c = cursor();
...@@ -291,7 +291,7 @@ QChar RefactoringFile::charAt(int pos) const ...@@ -291,7 +291,7 @@ QChar RefactoringFile::charAt(int pos) const
return QChar(); return QChar();
} }
QString RefactoringFile::textAt(int start, int end) const QString RefactoringFile::textOf(int start, int end) const
{ {
QTextCursor c = cursor(); QTextCursor c = cursor();
c.setPosition(start); c.setPosition(start);
...@@ -299,9 +299,9 @@ QString RefactoringFile::textAt(int start, int end) const ...@@ -299,9 +299,9 @@ QString RefactoringFile::textAt(int start, int end) const
return c.selectedText(); return c.selectedText();
} }
QString RefactoringFile::textAt(const Range &range) const QString RefactoringFile::textOf(const Range &range) const
{ {
return textAt(range.start, range.end); return textOf(range.start, range.end);
} }
bool RefactoringFile::change(const Utils::ChangeSet &changeSet, bool openEditor) bool RefactoringFile::change(const Utils::ChangeSet &changeSet, bool openEditor)
......
...@@ -51,7 +51,7 @@ public: ...@@ -51,7 +51,7 @@ public:
RefactoringFile(); RefactoringFile();
RefactoringFile(const QString &fileName, RefactoringChanges *refactoringChanges); RefactoringFile(const QString &fileName, RefactoringChanges *refactoringChanges);
RefactoringFile(const RefactoringFile &other); RefactoringFile(const RefactoringFile &other);
~RefactoringFile(); virtual ~RefactoringFile();
bool isValid() const; bool isValid() const;
...@@ -63,19 +63,19 @@ public: ...@@ -63,19 +63,19 @@ public:
int position(unsigned line, unsigned column) const; int position(unsigned line, unsigned column) const;
QChar charAt(int pos) const; QChar charAt(int pos) const;
QString textAt(int start, int end) const; QString textOf(int start, int end) const;
QString textAt(const Range &range) const; QString textOf(const Range &range) const;
bool change(const Utils::ChangeSet &changeSet, bool openEditor = true); bool change(const Utils::ChangeSet &changeSet, bool openEditor = true);
bool indent(const Range &range, bool openEditor = true); bool indent(const Range &range, bool openEditor = true);
private: protected:
// not assignable // not assignable
//const RefactoringFile &operator=(const RefactoringFile &other);