From 7ae3fd5a10c584de0f0f0d1ff7761266eadc68d0 Mon Sep 17 00:00:00 2001
From: Christian Kamm <christian.d.kamm@nokia.com>
Date: Wed, 7 Jul 2010 11:01:38 +0200
Subject: [PATCH] C++ indenter: Refactor to be independent of
 BaseTextDocumentLayout.

Done-with: Thomas Hartmann
---
 src/plugins/cppeditor/cppeditor.cpp           |   3 +-
 src/plugins/cpptools/cppcodeformatter.cpp     | 156 ++++++++++--------
 src/plugins/cpptools/cppcodeformatter.h       |  30 +++-
 .../texteditor/basetextdocumentlayout.cpp     |   5 -
 .../texteditor/basetextdocumentlayout.h       |   7 -
 5 files changed, 117 insertions(+), 84 deletions(-)

diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index c21a5948d3c..cc4238013a0 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -1791,7 +1791,8 @@ void CPPEditor::setFontSettings(const TextEditor::FontSettings &fs)
 
 void CPPEditor::setTabSettings(const TextEditor::TabSettings &ts)
 {
-    CppTools::CodeFormatter::invalidateCache(document());
+    CppTools::QtStyleCodeFormatter formatter;
+    formatter.invalidateCache(document());
 
     TextEditor::BaseTextEditor::setTabSettings(ts);
 }
diff --git a/src/plugins/cpptools/cppcodeformatter.cpp b/src/plugins/cpptools/cppcodeformatter.cpp
index ac4d94faf9e..5d42edef6d0 100644
--- a/src/plugins/cpptools/cppcodeformatter.cpp
+++ b/src/plugins/cpptools/cppcodeformatter.cpp
@@ -10,33 +10,16 @@
 #include <QtGui/QTextCursor>
 #include <QtGui/QTextBlock>
 
-namespace CppTools {
-namespace Internal {
-    class CppCodeFormatterData: public TextEditor::CodeFormatterData
-    {
-    public:
-        CppCodeFormatterData(int blockRevision,
-                             const QStack<CodeFormatter::State> &beginState,
-                             const QStack<CodeFormatter::State> &endState,
-                             int indentDepth)
-            : CodeFormatterData(blockRevision)
-            , m_beginState(beginState)
-            , m_endState(endState)
-            , m_indentDepth(indentDepth)
-        {}
-
-        QStack<CodeFormatter::State> m_beginState;
-        QStack<CodeFormatter::State> m_endState;
-        int m_indentDepth;
-    };
-}
-}
-
 using namespace CPlusPlus;
 using namespace CppTools;
 using namespace TextEditor;
 using namespace CppTools::Internal;
 
+CodeFormatter::BlockData::BlockData()
+    : m_blockRevision(-1)
+{
+}
+
 CodeFormatter::CodeFormatter()
     : m_indentDepth(0)
     , m_tabSize(4)
@@ -54,7 +37,7 @@ void CodeFormatter::setTabSize(int tabSize)
 
 void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
 {
-    restoreBlockState(block.previous());
+    restoreCurrentState(block.previous());
 
     bool endedJoined = false;
     const int lexerState = tokenizeBlock(block, &endedJoined);
@@ -420,14 +403,14 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
     if (topState == cpp_macro && endedJoined)
         turnInto(cpp_macro_cont);
 
-    storeBlockState(block);
+    saveCurrentState(block);
 }
 
 int CodeFormatter::indentFor(const QTextBlock &block)
 {
 //    qDebug() << "indenting for" << block.blockNumber() + 1;
 
-    restoreBlockState(block.previous());
+    restoreCurrentState(block.previous());
     correctIndentation(block);
     return m_indentDepth;
 }
@@ -439,18 +422,17 @@ void CodeFormatter::updateStateUntil(const QTextBlock &endBlock)
 
     // find the first block that needs recalculation
     for (; it.isValid() && it != endBlock; it = it.next()) {
-        TextBlockUserData *userData = BaseTextDocumentLayout::userData(it);
-        CppCodeFormatterData *cppData = static_cast<CppCodeFormatterData *>(userData->codeFormatterData());
-        if (!cppData)
+        BlockData blockData;
+        if (!loadBlockData(it, &blockData))
             break;
-        if (cppData->blockRevision() != it.revision())
+        if (blockData.m_blockRevision != it.revision())
             break;
-        if (previousState != cppData->m_beginState)
+        if (previousState != blockData.m_beginState)
             break;
-        if (TextBlockUserData::lexerState(it) == -1)
+        if (loadLexerState(it) == -1)
             break;
 
-        previousState = cppData->m_endState;
+        previousState = blockData.m_endState;
     }
 
     if (it == endBlock)
@@ -462,10 +444,10 @@ void CodeFormatter::updateStateUntil(const QTextBlock &endBlock)
     }
 
     // invalidate everything below by marking the state in endBlock as invalid
-    TextBlockUserData *userData = BaseTextDocumentLayout::userData(endBlock);
-    CppCodeFormatterData *cppData = static_cast<CppCodeFormatterData *>(userData->codeFormatterData());
-    if (cppData)
-        cppData->setBlockRevision(-1);
+    if (it.isValid()) {
+        BlockData invalidBlockData;
+        saveBlockData(&it, invalidBlockData);
+    }
 }
 
 void CodeFormatter::updateLineStateChange(const QTextBlock &block)
@@ -473,26 +455,18 @@ void CodeFormatter::updateLineStateChange(const QTextBlock &block)
     if (!block.isValid())
         return;
 
-    QStack<State> oldEndState;
-
-    TextBlockUserData *userData = BaseTextDocumentLayout::userData(block);
-    CppCodeFormatterData *cppData = static_cast<CppCodeFormatterData *>(userData->codeFormatterData());
-    if (cppData)
-        oldEndState = cppData->m_endState;
+    BlockData blockData;
+    if (loadBlockData(block, &blockData) && blockData.m_blockRevision == block.revision())
+        return;
 
     recalculateStateAfter(block);
 
-    if (oldEndState.isEmpty() || oldEndState != cppData->m_endState) {
-        // invalidate everything below by marking the next block's state as invalid
-        QTextBlock next = block.next();
-        if (!next.isValid())
-            return;
+    // invalidate everything below by marking the next block's state as invalid
+    QTextBlock next = block.next();
+    if (!next.isValid())
+        return;
 
-        userData = BaseTextDocumentLayout::userData(next);
-        cppData = static_cast<CppCodeFormatterData *>(userData->codeFormatterData());
-        if (cppData)
-            cppData->setBlockRevision(-1);
-    }
+    saveBlockData(&next, BlockData());
 }
 
 CodeFormatter::State CodeFormatter::state(int belowTop) const
@@ -528,13 +502,10 @@ void CodeFormatter::invalidateCache(QTextDocument *document)
     if (!document)
         return;
 
+    BlockData invalidBlockData;
     QTextBlock it = document->firstBlock();
     for (; it.isValid(); it = it.next()) {
-        TextBlockUserData *userData = BaseTextDocumentLayout::userData(it);
-        CppCodeFormatterData *cppData = static_cast<CppCodeFormatterData *>(userData->codeFormatterData());
-        if (!cppData)
-            break;
-        cppData->setBlockRevision(-1);
+        saveBlockData(&it, invalidBlockData);
     }
 }
 
@@ -795,25 +766,29 @@ void CodeFormatter::turnInto(int newState)
     enter(newState);
 }
 
-void CodeFormatter::storeBlockState(const QTextBlock &block)
+void CodeFormatter::saveCurrentState(const QTextBlock &block)
 {
     if (!block.isValid())
         return;
 
-    TextBlockUserData *userData = BaseTextDocumentLayout::userData(block);
-    userData->setCodeFormatterData(
-            new CppCodeFormatterData(block.revision(), m_beginState, m_currentState, m_indentDepth));
+    BlockData blockData;
+    blockData.m_blockRevision = block.revision();
+    blockData.m_beginState = m_beginState;
+    blockData.m_endState = m_currentState;
+    blockData.m_indentDepth = m_indentDepth;
+
+    QTextBlock saveableBlock(block);
+    saveBlockData(&saveableBlock, blockData);
 }
 
-void CodeFormatter::restoreBlockState(const QTextBlock &block)
+void CodeFormatter::restoreCurrentState(const QTextBlock &block)
 {
     if (block.isValid()) {             
-        TextBlockUserData *userData = BaseTextDocumentLayout::userData(block);
-        CppCodeFormatterData *oldData = static_cast<CppCodeFormatterData *>(userData->codeFormatterData());
-        if (oldData) {
-            m_currentState = oldData->m_endState;
+        BlockData blockData;
+        if (loadBlockData(block, &blockData)) {
+            m_indentDepth = blockData.m_indentDepth;
+            m_currentState = blockData.m_endState;
             m_beginState = m_currentState;
-            m_indentDepth = oldData->m_indentDepth;
             return;
         }
     }
@@ -833,7 +808,7 @@ QStack<CodeFormatter::State> CodeFormatter::initialState()
 
 int CodeFormatter::tokenizeBlock(const QTextBlock &block, bool *endedJoined)
 {
-    int startState = TextBlockUserData::lexerState(block.previous());
+    int startState = loadLexerState(block.previous());
     if (block.blockNumber() == 0)
         startState = 0;
     Q_ASSERT(startState != -1);
@@ -866,6 +841,17 @@ void CodeFormatter::dump()
     qDebug() << "Current indent depth:" << m_indentDepth;
 }
 
+
+namespace CppTools {
+namespace Internal {
+    class CppCodeFormatterData: public TextEditor::CodeFormatterData
+    {
+    public:
+        CodeFormatter::BlockData m_data;
+    };
+}
+}
+
 QtStyleCodeFormatter::QtStyleCodeFormatter()
     : m_indentSize(4)
     , m_indentSubstatementBraces(false)
@@ -900,6 +886,40 @@ void QtStyleCodeFormatter::setIndentDeclarationMembers(bool onOff)
     m_indentDeclarationMembers = onOff;
 }
 
+void QtStyleCodeFormatter::saveBlockData(QTextBlock *block, const BlockData &data) const
+{
+    TextBlockUserData *userData = BaseTextDocumentLayout::userData(*block);
+    CppCodeFormatterData *cppData = static_cast<CppCodeFormatterData *>(userData->codeFormatterData());
+    if (!cppData) {
+        cppData = new CppCodeFormatterData;
+        userData->setCodeFormatterData(cppData);
+    }
+    cppData->m_data = data;
+}
+
+bool QtStyleCodeFormatter::loadBlockData(const QTextBlock &block, BlockData *data) const
+{
+    TextBlockUserData *userData = BaseTextDocumentLayout::testUserData(block);
+    if (!userData)
+        return false;
+    CppCodeFormatterData *cppData = static_cast<CppCodeFormatterData *>(userData->codeFormatterData());
+    if (!cppData)
+        return false;
+
+    *data = cppData->m_data;
+    return true;
+}
+
+void QtStyleCodeFormatter::saveLexerState(QTextBlock *block, int state) const
+{
+    TextBlockUserData::setLexerState(*block, state);
+}
+
+int QtStyleCodeFormatter::loadLexerState(const QTextBlock &block) const
+{
+    return TextBlockUserData::lexerState(block);
+}
+
 void QtStyleCodeFormatter::onEnter(int newState, int *indentDepth, int *savedIndentDepth) const
 {
     const State &parentState = state();
diff --git a/src/plugins/cpptools/cppcodeformatter.h b/src/plugins/cpptools/cppcodeformatter.h
index 4fee466086c..18b02cea1bf 100644
--- a/src/plugins/cpptools/cppcodeformatter.h
+++ b/src/plugins/cpptools/cppcodeformatter.h
@@ -39,12 +39,30 @@ public:
 
     void setTabSize(int tabSize);
 
-    static void invalidateCache(QTextDocument *document);
+    void invalidateCache(QTextDocument *document);
 
 protected:
     virtual void onEnter(int newState, int *indentDepth, int *savedIndentDepth) const = 0;
     virtual void adjustIndent(const QList<CPlusPlus::Token> &tokens, int lexerState, int *indentDepth) const = 0;
 
+    class State;
+    class BlockData
+    {
+    public:
+        BlockData();
+
+        QStack<State> m_beginState;
+        QStack<State> m_endState;
+        int m_indentDepth;
+        int m_blockRevision;
+    };
+
+    virtual void saveBlockData(QTextBlock *block, const BlockData &data) const = 0;
+    virtual bool loadBlockData(const QTextBlock &block, BlockData *data) const = 0;
+
+    virtual void saveLexerState(QTextBlock *block, int state) const = 0;
+    virtual int loadLexerState(const QTextBlock &block) const = 0;
+
 protected:
     enum StateType {
         invalid = 0,
@@ -146,8 +164,8 @@ protected:
 
 private:
     void recalculateStateAfter(const QTextBlock &block);
-    void storeBlockState(const QTextBlock &block);
-    void restoreBlockState(const QTextBlock &block);
+    void saveCurrentState(const QTextBlock &block);
+    void restoreCurrentState(const QTextBlock &block);
 
     QStringRef currentTokenText() const;
 
@@ -201,6 +219,12 @@ protected:
     virtual void onEnter(int newState, int *indentDepth, int *savedIndentDepth) const;
     virtual void adjustIndent(const QList<CPlusPlus::Token> &tokens, int lexerState, int *indentDepth) const;
 
+    virtual void saveBlockData(QTextBlock *block, const BlockData &data) const;
+    virtual bool loadBlockData(const QTextBlock &block, BlockData *data) const;
+
+    virtual void saveLexerState(QTextBlock *block, int state) const;
+    virtual int loadLexerState(const QTextBlock &block) const;
+
 private:
     int m_indentSize;
     bool m_indentSubstatementBraces;
diff --git a/src/plugins/texteditor/basetextdocumentlayout.cpp b/src/plugins/texteditor/basetextdocumentlayout.cpp
index 871cab0e131..087eb09ccff 100644
--- a/src/plugins/texteditor/basetextdocumentlayout.cpp
+++ b/src/plugins/texteditor/basetextdocumentlayout.cpp
@@ -31,11 +31,6 @@
 
 using namespace TextEditor;
 
-CodeFormatterData::CodeFormatterData(int blockRevision)
-    : m_blockRevision(blockRevision)
-{
-}
-
 CodeFormatterData::~CodeFormatterData()
 {
 }
diff --git a/src/plugins/texteditor/basetextdocumentlayout.h b/src/plugins/texteditor/basetextdocumentlayout.h
index 76323c63841..d6fa481ec74 100644
--- a/src/plugins/texteditor/basetextdocumentlayout.h
+++ b/src/plugins/texteditor/basetextdocumentlayout.h
@@ -57,14 +57,7 @@ struct TEXTEDITOR_EXPORT Parenthesis
 class TEXTEDITOR_EXPORT CodeFormatterData
 {
 public:
-    CodeFormatterData(int blockRevision);
     virtual ~CodeFormatterData();
-
-    int blockRevision() const { return m_blockRevision; }
-    void setBlockRevision(int revision) { m_blockRevision = revision; }
-
-private:
-    int m_blockRevision;
 };
 
 class TEXTEDITOR_EXPORT TextBlockUserData : public QTextBlockUserData
-- 
GitLab