diff --git a/src/plugins/cppeditor/cppdeclfromdef.cpp b/src/plugins/cppeditor/cppdeclfromdef.cpp index c3f312a60c5a4cadcac35e607710670869c48872..0730ed8d85ad7d71bd35c663d3b2372b50638755 100644 --- a/src/plugins/cppeditor/cppdeclfromdef.cpp +++ b/src/plugins/cppeditor/cppdeclfromdef.cpp @@ -82,10 +82,10 @@ public: "CppEditor::DeclFromDef").arg(type)); } - void performChanges(TextEditor::RefactoringFile *, CppRefactoringChanges *refactoring) + void performChanges(CppRefactoringFile *, CppRefactoringChanges *refactoring) { - TextEditor::RefactoringFile targetFile = refactoring->file(m_targetFileName); - Document::Ptr targetDoc = refactoring->document(targetFile); + CppRefactoringFile targetFile = refactoring->file(m_targetFileName); + Document::Ptr targetDoc = targetFile.cppDocument(); InsertionPointLocator locator(targetDoc); const InsertionLocation loc = locator.methodDeclarationInClass(m_targetSymbol, m_xsSpec); Q_ASSERT(loc.isValid()); diff --git a/src/plugins/cppeditor/cppquickfix.cpp b/src/plugins/cppeditor/cppquickfix.cpp index 1441f1c143347402550337e524d0d74acb654dba..c85e776f3a678eab3731234e122706b01aa10d0c 100644 --- a/src/plugins/cppeditor/cppquickfix.cpp +++ b/src/plugins/cppeditor/cppquickfix.cpp @@ -192,7 +192,7 @@ CppQuickFixOperation::~CppQuickFixOperation() void CppQuickFixOperation::perform() { CppRefactoringChanges refactoring(_state.document(), _state.snapshot()); - TextEditor::RefactoringFile current = refactoring.file(fileName()); + CppRefactoringFile current = refactoring.file(fileName()); performChanges(¤t, &refactoring); } diff --git a/src/plugins/cppeditor/cppquickfix.h b/src/plugins/cppeditor/cppquickfix.h index 6206ffdcac3bad6b35b99f209e74f7e2e1f98808..53b8a0786e4a6ab6fbb3cdcaa26ea8a700eb5367 100644 --- a/src/plugins/cppeditor/cppquickfix.h +++ b/src/plugins/cppeditor/cppquickfix.h @@ -110,7 +110,7 @@ public: virtual void perform(); protected: - virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *refactoring) = 0; + virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *refactoring) = 0; QString fileName() const; diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp index a7a0e089cefdfcd9f519f882fb09d8fb6ae2cc0f..7b9c208505f66de1ebafa47b2a405a53cb101575 100644 --- a/src/plugins/cppeditor/cppquickfixes.cpp +++ b/src/plugins/cppeditor/cppquickfixes.cpp @@ -148,7 +148,7 @@ private: 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; if (negation) { @@ -243,7 +243,7 @@ private: 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; @@ -321,7 +321,7 @@ private: pattern = mk->BinaryExpression(left, right); } - virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *) + virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *) { ChangeSet changes; changes.replace(range(pattern->binary_op_token), QLatin1String("||")); @@ -422,7 +422,7 @@ private: "Split Declaration")); } - virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *) + virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *) { ChangeSet changes; @@ -505,7 +505,7 @@ private: "Add Curly Braces")); } - virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *) + virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *) { ChangeSet changes; @@ -576,7 +576,7 @@ private: pattern = mk.IfStatement(condition); } - virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *) + virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *) { ChangeSet changes; @@ -658,7 +658,7 @@ private: pattern = mk.WhileStatement(condition); } - virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *) + virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *) { ChangeSet changes; @@ -767,7 +767,7 @@ private: "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); @@ -777,7 +777,7 @@ private: splitOrCondition(currentFile); } - void splitAndCondition(TextEditor::RefactoringFile *currentFile) + void splitAndCondition(CppRefactoringFile *currentFile) { ChangeSet changes; @@ -794,7 +794,7 @@ private: currentFile->indent(range(pattern)); } - void splitOrCondition(TextEditor::RefactoringFile *currentFile) + void splitOrCondition(CppRefactoringFile *currentFile) { ChangeSet changes; @@ -905,7 +905,7 @@ private: "Enclose in QLatin1String(...)")); } - virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *) + virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *) { ChangeSet changes; @@ -1026,7 +1026,7 @@ private: setDescription(QApplication::translate("CppTools::QuickFix", "Mark as translateable")); } - virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *) + virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *) { ChangeSet changes; @@ -1107,7 +1107,7 @@ private: "Convert to Objective-C String Literal")); } - virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *) + virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *) { ChangeSet changes; @@ -1255,7 +1255,7 @@ private: , replacement(replacement) {} - virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *) + virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *) { ChangeSet changes; changes.replace(start, end, replacement); @@ -1409,7 +1409,7 @@ private: } - virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *) + virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *) { ChangeSet changes; int start = endOf(compoundStatement->lbrace_token); @@ -1485,7 +1485,7 @@ private: "#include header file")); } - virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *) + virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *) { Q_ASSERT(fwdClass != 0); @@ -1599,7 +1599,7 @@ private: setDescription(QApplication::translate("CppTools::QuickFix", "Add local declaration")); } - virtual void performChanges(TextEditor::RefactoringFile *currentFile, CppRefactoringChanges *) + virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *) { TypeOfExpression typeOfExpression; typeOfExpression.init(state().document(), state().snapshot(), state().context().bindings()); @@ -1687,7 +1687,7 @@ private: "Convert to Camel Case ...")); } - virtual void performChanges(TextEditor::RefactoringFile *, CppRefactoringChanges *) + virtual void performChanges(CppRefactoringFile *, CppRefactoringChanges *) { for (int i = 1; i < m_name.length(); ++i) { QCharRef c = m_name[i]; diff --git a/src/plugins/cppeditor/cpprefactoringchanges.cpp b/src/plugins/cppeditor/cpprefactoringchanges.cpp index 6ed66578652e6e789567037e2b184183f11b5e69..25050360ea26f8bde81d830826ab239b308976b3 100644 --- a/src/plugins/cppeditor/cpprefactoringchanges.cpp +++ b/src/plugins/cppeditor/cpprefactoringchanges.cpp @@ -29,6 +29,8 @@ #include "cpprefactoringchanges.h" +#include <TranslationUnit.h> +#include <AST.h> #include <cpptools/cppcodeformatter.h> #include <texteditor/texteditorsettings.h> #include <texteditor/tabsettings.h> @@ -37,6 +39,7 @@ using namespace CppEditor; using namespace CPlusPlus; +using namespace Utils; CppRefactoringChanges::CppRefactoringChanges(const Document::Ptr &thisDocument, const Snapshot &snapshot) : m_thisDocument(thisDocument) @@ -63,16 +66,9 @@ const LookupContext &CppRefactoringChanges::context() const return m_context; } -Document::Ptr CppRefactoringChanges::document(const TextEditor::RefactoringFile &file) const +CppRefactoringFile CppRefactoringChanges::file(const QString &fileName) { - QString source = file.document()->toPlainText(); - QString fileName = file.fileName(); - - const QByteArray contents = m_snapshot.preprocessedCode(source, fileName); - Document::Ptr doc = m_snapshot.documentFromSource(contents, fileName); - doc->check(); - - return doc; + return CppRefactoringFile(fileName, this); } void CppRefactoringChanges::indentSelection(const QTextCursor &selection) const @@ -98,3 +94,126 @@ void CppRefactoringChanges::fileChanged(const QString &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); +} diff --git a/src/plugins/cppeditor/cpprefactoringchanges.h b/src/plugins/cppeditor/cpprefactoringchanges.h index 7c8d13687967d321e58cfda384d9bf9527cdf401..9a7e21525539141acb6d4b86d2231ed28331157f 100644 --- a/src/plugins/cppeditor/cpprefactoringchanges.h +++ b/src/plugins/cppeditor/cpprefactoringchanges.h @@ -30,6 +30,7 @@ #ifndef CPPREFACTORINGCHANGES_H #define CPPREFACTORINGCHANGES_H +#include <ASTfwd.h> #include <cplusplus/CppDocument.h> #include <cplusplus/LookupContext.h> @@ -40,6 +41,43 @@ 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 { public: @@ -50,7 +88,7 @@ public: const CPlusPlus::Snapshot &snapshot() const; const CPlusPlus::LookupContext &context() const; - CPlusPlus::Document::Ptr document(const TextEditor::RefactoringFile &file) const; + CppRefactoringFile file(const QString &fileName); private: virtual void indentSelection(const QTextCursor &selection) const; diff --git a/src/plugins/texteditor/refactoringchanges.cpp b/src/plugins/texteditor/refactoringchanges.cpp index 74fa69a3a8f4e325b267357aaf26844fcaa1ae88..25da5bafae139927a9b8729750fff8d9b9477d53 100644 --- a/src/plugins/texteditor/refactoringchanges.cpp +++ b/src/plugins/texteditor/refactoringchanges.cpp @@ -196,11 +196,11 @@ RefactoringFile::RefactoringFile(const RefactoringFile &other) RefactoringFile::~RefactoringFile() { - if (m_openEditor) + if (m_refactoringChanges && m_openEditor) m_editor = m_refactoringChanges->openEditor(m_fileName, -1); // apply changes, if any - if (!m_indentRanges.isEmpty() || !m_changes.isEmpty()) { + if (m_refactoringChanges && !(m_indentRanges.isEmpty() && m_changes.isEmpty())) { QTextDocument *doc = mutableDocument(); { QTextCursor c = cursor(); @@ -291,7 +291,7 @@ QChar RefactoringFile::charAt(int pos) const return QChar(); } -QString RefactoringFile::textAt(int start, int end) const +QString RefactoringFile::textOf(int start, int end) const { QTextCursor c = cursor(); c.setPosition(start); @@ -299,9 +299,9 @@ QString RefactoringFile::textAt(int start, int end) const 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) diff --git a/src/plugins/texteditor/refactoringchanges.h b/src/plugins/texteditor/refactoringchanges.h index fc67d43f8519476ae309bd30ecbc96f8c52b77a2..257c7163d1480bdf3a4593cf096f12b933b2c620 100644 --- a/src/plugins/texteditor/refactoringchanges.h +++ b/src/plugins/texteditor/refactoringchanges.h @@ -51,7 +51,7 @@ public: RefactoringFile(); RefactoringFile(const QString &fileName, RefactoringChanges *refactoringChanges); RefactoringFile(const RefactoringFile &other); - ~RefactoringFile(); + virtual ~RefactoringFile(); bool isValid() const; @@ -63,19 +63,19 @@ public: int position(unsigned line, unsigned column) const; QChar charAt(int pos) const; - QString textAt(int start, int end) const; - QString textAt(const Range &range) const; + QString textOf(int start, int end) const; + QString textOf(const Range &range) const; bool change(const Utils::ChangeSet &changeSet, bool openEditor = true); bool indent(const Range &range, bool openEditor = true); -private: +protected: // not assignable //const RefactoringFile &operator=(const RefactoringFile &other); QTextDocument *mutableDocument() const; -private: +protected: QString m_fileName; RefactoringChanges *m_refactoringChanges; mutable QTextDocument *m_document;