C++ indenter: Refactor to be independent of BaseTextDocumentLayout.

Done-with: Thomas Hartmann
This commit is contained in:
Christian Kamm
2010-07-07 11:01:38 +02:00
parent 486b23b8ef
commit 7ae3fd5a10
5 changed files with 117 additions and 84 deletions

View File

@@ -1791,7 +1791,8 @@ void CPPEditor::setFontSettings(const TextEditor::FontSettings &fs)
void CPPEditor::setTabSettings(const TextEditor::TabSettings &ts) void CPPEditor::setTabSettings(const TextEditor::TabSettings &ts)
{ {
CppTools::CodeFormatter::invalidateCache(document()); CppTools::QtStyleCodeFormatter formatter;
formatter.invalidateCache(document());
TextEditor::BaseTextEditor::setTabSettings(ts); TextEditor::BaseTextEditor::setTabSettings(ts);
} }

View File

@@ -10,33 +10,16 @@
#include <QtGui/QTextCursor> #include <QtGui/QTextCursor>
#include <QtGui/QTextBlock> #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 CPlusPlus;
using namespace CppTools; using namespace CppTools;
using namespace TextEditor; using namespace TextEditor;
using namespace CppTools::Internal; using namespace CppTools::Internal;
CodeFormatter::BlockData::BlockData()
: m_blockRevision(-1)
{
}
CodeFormatter::CodeFormatter() CodeFormatter::CodeFormatter()
: m_indentDepth(0) : m_indentDepth(0)
, m_tabSize(4) , m_tabSize(4)
@@ -54,7 +37,7 @@ void CodeFormatter::setTabSize(int tabSize)
void CodeFormatter::recalculateStateAfter(const QTextBlock &block) void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
{ {
restoreBlockState(block.previous()); restoreCurrentState(block.previous());
bool endedJoined = false; bool endedJoined = false;
const int lexerState = tokenizeBlock(block, &endedJoined); const int lexerState = tokenizeBlock(block, &endedJoined);
@@ -420,14 +403,14 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
if (topState == cpp_macro && endedJoined) if (topState == cpp_macro && endedJoined)
turnInto(cpp_macro_cont); turnInto(cpp_macro_cont);
storeBlockState(block); saveCurrentState(block);
} }
int CodeFormatter::indentFor(const QTextBlock &block) int CodeFormatter::indentFor(const QTextBlock &block)
{ {
// qDebug() << "indenting for" << block.blockNumber() + 1; // qDebug() << "indenting for" << block.blockNumber() + 1;
restoreBlockState(block.previous()); restoreCurrentState(block.previous());
correctIndentation(block); correctIndentation(block);
return m_indentDepth; return m_indentDepth;
} }
@@ -439,18 +422,17 @@ void CodeFormatter::updateStateUntil(const QTextBlock &endBlock)
// find the first block that needs recalculation // find the first block that needs recalculation
for (; it.isValid() && it != endBlock; it = it.next()) { for (; it.isValid() && it != endBlock; it = it.next()) {
TextBlockUserData *userData = BaseTextDocumentLayout::userData(it); BlockData blockData;
CppCodeFormatterData *cppData = static_cast<CppCodeFormatterData *>(userData->codeFormatterData()); if (!loadBlockData(it, &blockData))
if (!cppData)
break; break;
if (cppData->blockRevision() != it.revision()) if (blockData.m_blockRevision != it.revision())
break; break;
if (previousState != cppData->m_beginState) if (previousState != blockData.m_beginState)
break; break;
if (TextBlockUserData::lexerState(it) == -1) if (loadLexerState(it) == -1)
break; break;
previousState = cppData->m_endState; previousState = blockData.m_endState;
} }
if (it == endBlock) if (it == endBlock)
@@ -462,10 +444,10 @@ void CodeFormatter::updateStateUntil(const QTextBlock &endBlock)
} }
// invalidate everything below by marking the state in endBlock as invalid // invalidate everything below by marking the state in endBlock as invalid
TextBlockUserData *userData = BaseTextDocumentLayout::userData(endBlock); if (it.isValid()) {
CppCodeFormatterData *cppData = static_cast<CppCodeFormatterData *>(userData->codeFormatterData()); BlockData invalidBlockData;
if (cppData) saveBlockData(&it, invalidBlockData);
cppData->setBlockRevision(-1); }
} }
void CodeFormatter::updateLineStateChange(const QTextBlock &block) void CodeFormatter::updateLineStateChange(const QTextBlock &block)
@@ -473,26 +455,18 @@ void CodeFormatter::updateLineStateChange(const QTextBlock &block)
if (!block.isValid()) if (!block.isValid())
return; return;
QStack<State> oldEndState; BlockData blockData;
if (loadBlockData(block, &blockData) && blockData.m_blockRevision == block.revision())
TextBlockUserData *userData = BaseTextDocumentLayout::userData(block); return;
CppCodeFormatterData *cppData = static_cast<CppCodeFormatterData *>(userData->codeFormatterData());
if (cppData)
oldEndState = cppData->m_endState;
recalculateStateAfter(block); recalculateStateAfter(block);
if (oldEndState.isEmpty() || oldEndState != cppData->m_endState) { // invalidate everything below by marking the next block's state as invalid
// invalidate everything below by marking the next block's state as invalid QTextBlock next = block.next();
QTextBlock next = block.next(); if (!next.isValid())
if (!next.isValid()) return;
return;
userData = BaseTextDocumentLayout::userData(next); saveBlockData(&next, BlockData());
cppData = static_cast<CppCodeFormatterData *>(userData->codeFormatterData());
if (cppData)
cppData->setBlockRevision(-1);
}
} }
CodeFormatter::State CodeFormatter::state(int belowTop) const CodeFormatter::State CodeFormatter::state(int belowTop) const
@@ -528,13 +502,10 @@ void CodeFormatter::invalidateCache(QTextDocument *document)
if (!document) if (!document)
return; return;
BlockData invalidBlockData;
QTextBlock it = document->firstBlock(); QTextBlock it = document->firstBlock();
for (; it.isValid(); it = it.next()) { for (; it.isValid(); it = it.next()) {
TextBlockUserData *userData = BaseTextDocumentLayout::userData(it); saveBlockData(&it, invalidBlockData);
CppCodeFormatterData *cppData = static_cast<CppCodeFormatterData *>(userData->codeFormatterData());
if (!cppData)
break;
cppData->setBlockRevision(-1);
} }
} }
@@ -795,25 +766,29 @@ void CodeFormatter::turnInto(int newState)
enter(newState); enter(newState);
} }
void CodeFormatter::storeBlockState(const QTextBlock &block) void CodeFormatter::saveCurrentState(const QTextBlock &block)
{ {
if (!block.isValid()) if (!block.isValid())
return; return;
TextBlockUserData *userData = BaseTextDocumentLayout::userData(block); BlockData blockData;
userData->setCodeFormatterData( blockData.m_blockRevision = block.revision();
new CppCodeFormatterData(block.revision(), m_beginState, m_currentState, m_indentDepth)); 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()) { if (block.isValid()) {
TextBlockUserData *userData = BaseTextDocumentLayout::userData(block); BlockData blockData;
CppCodeFormatterData *oldData = static_cast<CppCodeFormatterData *>(userData->codeFormatterData()); if (loadBlockData(block, &blockData)) {
if (oldData) { m_indentDepth = blockData.m_indentDepth;
m_currentState = oldData->m_endState; m_currentState = blockData.m_endState;
m_beginState = m_currentState; m_beginState = m_currentState;
m_indentDepth = oldData->m_indentDepth;
return; return;
} }
} }
@@ -833,7 +808,7 @@ QStack<CodeFormatter::State> CodeFormatter::initialState()
int CodeFormatter::tokenizeBlock(const QTextBlock &block, bool *endedJoined) int CodeFormatter::tokenizeBlock(const QTextBlock &block, bool *endedJoined)
{ {
int startState = TextBlockUserData::lexerState(block.previous()); int startState = loadLexerState(block.previous());
if (block.blockNumber() == 0) if (block.blockNumber() == 0)
startState = 0; startState = 0;
Q_ASSERT(startState != -1); Q_ASSERT(startState != -1);
@@ -866,6 +841,17 @@ void CodeFormatter::dump()
qDebug() << "Current indent depth:" << m_indentDepth; qDebug() << "Current indent depth:" << m_indentDepth;
} }
namespace CppTools {
namespace Internal {
class CppCodeFormatterData: public TextEditor::CodeFormatterData
{
public:
CodeFormatter::BlockData m_data;
};
}
}
QtStyleCodeFormatter::QtStyleCodeFormatter() QtStyleCodeFormatter::QtStyleCodeFormatter()
: m_indentSize(4) : m_indentSize(4)
, m_indentSubstatementBraces(false) , m_indentSubstatementBraces(false)
@@ -900,6 +886,40 @@ void QtStyleCodeFormatter::setIndentDeclarationMembers(bool onOff)
m_indentDeclarationMembers = 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 void QtStyleCodeFormatter::onEnter(int newState, int *indentDepth, int *savedIndentDepth) const
{ {
const State &parentState = state(); const State &parentState = state();

View File

@@ -39,12 +39,30 @@ public:
void setTabSize(int tabSize); void setTabSize(int tabSize);
static void invalidateCache(QTextDocument *document); void invalidateCache(QTextDocument *document);
protected: protected:
virtual void onEnter(int newState, int *indentDepth, int *savedIndentDepth) const = 0; 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; 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: protected:
enum StateType { enum StateType {
invalid = 0, invalid = 0,
@@ -146,8 +164,8 @@ protected:
private: private:
void recalculateStateAfter(const QTextBlock &block); void recalculateStateAfter(const QTextBlock &block);
void storeBlockState(const QTextBlock &block); void saveCurrentState(const QTextBlock &block);
void restoreBlockState(const QTextBlock &block); void restoreCurrentState(const QTextBlock &block);
QStringRef currentTokenText() const; QStringRef currentTokenText() const;
@@ -201,6 +219,12 @@ protected:
virtual void onEnter(int newState, int *indentDepth, int *savedIndentDepth) const; 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 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: private:
int m_indentSize; int m_indentSize;
bool m_indentSubstatementBraces; bool m_indentSubstatementBraces;

View File

@@ -31,11 +31,6 @@
using namespace TextEditor; using namespace TextEditor;
CodeFormatterData::CodeFormatterData(int blockRevision)
: m_blockRevision(blockRevision)
{
}
CodeFormatterData::~CodeFormatterData() CodeFormatterData::~CodeFormatterData()
{ {
} }

View File

@@ -57,14 +57,7 @@ struct TEXTEDITOR_EXPORT Parenthesis
class TEXTEDITOR_EXPORT CodeFormatterData class TEXTEDITOR_EXPORT CodeFormatterData
{ {
public: public:
CodeFormatterData(int blockRevision);
virtual ~CodeFormatterData(); 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 class TEXTEDITOR_EXPORT TextBlockUserData : public QTextBlockUserData