forked from qt-creator/qt-creator
C++ indenter: Make building custom styles easier, fix style issues.
Keep more information by using enter() instead of turnInto() when moving from a *_start to *_open.
This commit is contained in:
@@ -38,8 +38,7 @@ using namespace TextEditor;
|
||||
using namespace CppTools::Internal;
|
||||
|
||||
CodeFormatter::CodeFormatter()
|
||||
: m_document(0)
|
||||
, m_indentDepth(0)
|
||||
: m_indentDepth(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -47,11 +46,6 @@ CodeFormatter::~CodeFormatter()
|
||||
{
|
||||
}
|
||||
|
||||
void CodeFormatter::setDocument(QTextDocument *document)
|
||||
{
|
||||
m_document = document;
|
||||
}
|
||||
|
||||
void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
|
||||
{
|
||||
restoreBlockState(block.previous());
|
||||
@@ -59,6 +53,7 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
|
||||
bool endedJoined = false;
|
||||
const int lexerState = tokenizeBlock(block, &endedJoined);
|
||||
m_tokenIndex = 0;
|
||||
m_newStates.clear();
|
||||
|
||||
if (tokenAt(0).kind() == T_POUND) {
|
||||
enter(cpp_macro_start);
|
||||
@@ -84,7 +79,8 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
|
||||
|
||||
case namespace_start:
|
||||
switch (kind) {
|
||||
case T_LBRACE: turnInto(namespace_open); break;
|
||||
case T_LBRACE: enter(namespace_open); break;
|
||||
case T_RBRACE: leave(); break;
|
||||
} break;
|
||||
|
||||
case namespace_open:
|
||||
@@ -92,7 +88,7 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
|
||||
break;
|
||||
switch (kind) {
|
||||
case T_NAMESPACE: enter(namespace_start); break;
|
||||
case T_RBRACE: leave(); break;
|
||||
case T_RBRACE: leave(); continue; // always nested in namespace_start
|
||||
case T_STRUCT:
|
||||
case T_UNION:
|
||||
case T_CLASS: enter(class_start); break;
|
||||
@@ -103,14 +99,14 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
|
||||
case class_start:
|
||||
switch (kind) {
|
||||
case T_SEMICOLON: leave(); break;
|
||||
case T_LBRACE: turnInto(class_open); break;
|
||||
case T_LBRACE: enter(class_open); break;
|
||||
} break;
|
||||
|
||||
case class_open:
|
||||
if (tryDeclaration())
|
||||
break;
|
||||
switch (kind) {
|
||||
case T_RBRACE: leave(); break;
|
||||
case T_RBRACE: leave(); continue; // always nested in class_start
|
||||
case T_STRUCT:
|
||||
case T_UNION:
|
||||
case T_CLASS: enter(class_start); break;
|
||||
@@ -121,13 +117,19 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
|
||||
case enum_start:
|
||||
switch (kind) {
|
||||
case T_SEMICOLON: leave(); break;
|
||||
case T_LBRACE: turnInto(brace_list_open); break;
|
||||
case T_LBRACE: enter(enum_open); break;
|
||||
} break;
|
||||
|
||||
case enum_open:
|
||||
switch (kind) {
|
||||
case T_RBRACE: leave(); continue; // always nested in enum_start
|
||||
case T_LBRACE: enter(brace_list_open); break;
|
||||
} break;
|
||||
|
||||
case brace_list_open:
|
||||
switch (kind) {
|
||||
case T_RBRACE: leave(); break;
|
||||
case T_LBRACE: enter(brace_list_open); break; // ### Other, nested brace list?
|
||||
case T_LBRACE: enter(brace_list_open); break;
|
||||
} break;
|
||||
|
||||
case using_start:
|
||||
@@ -156,10 +158,11 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
|
||||
if (tryExpression(true))
|
||||
break;
|
||||
switch (kind) {
|
||||
case T_RBRACE:
|
||||
case T_SEMICOLON: leave(true); break;
|
||||
case T_EQUAL: enter(initializer); break;
|
||||
case T_LBRACE: turnInto(defun_open); break;
|
||||
case T_COLON: turnInto(member_init_open); break;
|
||||
case T_LBRACE: enter(defun_open); break;
|
||||
case T_COLON: enter(member_init_open); break;
|
||||
case T_OPERATOR: enter(operator_declaration); break;
|
||||
} break;
|
||||
|
||||
@@ -211,14 +214,14 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
|
||||
case member_init_open:
|
||||
switch (kind) {
|
||||
case T_LBRACE: turnInto(defun_open); break;
|
||||
case T_SEMICOLON: leave(); break; // ### so we don't break completely if it's a bitfield or ternary
|
||||
case T_SEMICOLON: leave(); continue; // so we don't break completely if it's a bitfield or ternary
|
||||
} break;
|
||||
|
||||
case defun_open:
|
||||
if (tryStatement())
|
||||
break;
|
||||
switch (kind) {
|
||||
case T_RBRACE: leave(); break;
|
||||
case T_RBRACE: leave(); continue; // always nested in declaration_start
|
||||
} break;
|
||||
|
||||
case switch_statement:
|
||||
@@ -437,9 +440,6 @@ int CodeFormatter::indentFor(const QTextBlock &block)
|
||||
{
|
||||
// qDebug() << "indenting for" << block.blockNumber() + 1;
|
||||
|
||||
Q_ASSERT(m_document);
|
||||
Q_ASSERT(m_document == block.document());
|
||||
|
||||
requireStatesUntil(block);
|
||||
correctIndentation(block);
|
||||
return m_indentDepth;
|
||||
@@ -448,7 +448,7 @@ int CodeFormatter::indentFor(const QTextBlock &block)
|
||||
void CodeFormatter::requireStatesUntil(const QTextBlock &endBlock)
|
||||
{
|
||||
QStack<State> previousState = initialState();
|
||||
QTextBlock it = m_document->firstBlock();
|
||||
QTextBlock it = endBlock.document()->firstBlock();
|
||||
for (; it.isValid() && it != endBlock; it = it.next()) {
|
||||
TextBlockUserData *userData = BaseTextDocumentLayout::userData(it);
|
||||
CppCodeFormatterData *cppData = static_cast<CppCodeFormatterData *>(userData->codeFormatterData());
|
||||
@@ -478,14 +478,19 @@ CodeFormatter::State CodeFormatter::state(int belowTop) const
|
||||
return State();
|
||||
}
|
||||
|
||||
const QVector<CodeFormatter::State> &CodeFormatter::newStatesThisLine() const
|
||||
{
|
||||
return m_newStates;
|
||||
}
|
||||
|
||||
int CodeFormatter::tokenIndex() const
|
||||
{
|
||||
return m_tokenIndex;
|
||||
}
|
||||
|
||||
int CodeFormatter::tokenIndexFromEnd() const
|
||||
int CodeFormatter::tokenCount() const
|
||||
{
|
||||
return m_tokens.size() - 1 - m_tokenIndex;
|
||||
return m_tokens.size();
|
||||
}
|
||||
|
||||
const CPlusPlus::Token &CodeFormatter::currentToken() const
|
||||
@@ -493,9 +498,12 @@ const CPlusPlus::Token &CodeFormatter::currentToken() const
|
||||
return m_currentToken;
|
||||
}
|
||||
|
||||
void CodeFormatter::invalidateCache()
|
||||
void CodeFormatter::invalidateCache(QTextDocument *document)
|
||||
{
|
||||
QTextBlock it = m_document->firstBlock();
|
||||
if (!document)
|
||||
return;
|
||||
|
||||
QTextBlock it = document->firstBlock();
|
||||
for (; it.isValid(); it = it.next()) {
|
||||
TextBlockUserData *userData = BaseTextDocumentLayout::userData(it);
|
||||
CppCodeFormatterData *cppData = static_cast<CppCodeFormatterData *>(userData->codeFormatterData());
|
||||
@@ -509,7 +517,9 @@ void CodeFormatter::enter(int newState)
|
||||
{
|
||||
int savedIndentDepth = m_indentDepth;
|
||||
onEnter(newState, &m_indentDepth, &savedIndentDepth);
|
||||
m_currentState.push(State(newState, savedIndentDepth));
|
||||
State s(newState, savedIndentDepth);
|
||||
m_currentState.push(s);
|
||||
m_newStates.push(s);
|
||||
}
|
||||
|
||||
void CodeFormatter::leave(bool statementDone)
|
||||
@@ -518,6 +528,9 @@ void CodeFormatter::leave(bool statementDone)
|
||||
if (m_currentState.top().type == topmost_intro)
|
||||
return;
|
||||
|
||||
if (m_newStates.size() > 0)
|
||||
m_newStates.pop();
|
||||
|
||||
// restore indent depth
|
||||
State poppedState = m_currentState.pop();
|
||||
m_indentDepth = poppedState.savedIndentDepth;
|
||||
@@ -794,24 +807,36 @@ void CodeFormatter::dump()
|
||||
|
||||
QtStyleCodeFormatter::QtStyleCodeFormatter()
|
||||
: m_indentSize(4)
|
||||
, m_style(QtStyle)
|
||||
, m_indentSubstatementBraces(false)
|
||||
, m_indentSubstatementStatements(true)
|
||||
, m_indentDeclarationBraces(false)
|
||||
, m_indentDeclarationMembers(true)
|
||||
{
|
||||
}
|
||||
|
||||
void QtStyleCodeFormatter::setIndentSize(int size)
|
||||
{
|
||||
if (size != m_indentSize) {
|
||||
m_indentSize = size;
|
||||
invalidateCache();
|
||||
}
|
||||
m_indentSize = size;
|
||||
}
|
||||
|
||||
void QtStyleCodeFormatter::setCompoundStyle(CompoundStyle style)
|
||||
void QtStyleCodeFormatter::setIndentSubstatementBraces(bool onOff)
|
||||
{
|
||||
if (style != m_style) {
|
||||
m_style = style;
|
||||
invalidateCache();
|
||||
}
|
||||
m_indentSubstatementBraces = onOff;
|
||||
}
|
||||
|
||||
void QtStyleCodeFormatter::setIndentSubstatementStatements(bool onOff)
|
||||
{
|
||||
m_indentSubstatementStatements = onOff;
|
||||
}
|
||||
|
||||
void QtStyleCodeFormatter::setIndentDeclarationBraces(bool onOff)
|
||||
{
|
||||
m_indentDeclarationBraces = onOff;
|
||||
}
|
||||
|
||||
void QtStyleCodeFormatter::setIndentDeclarationMembers(bool onOff)
|
||||
{
|
||||
m_indentDeclarationMembers = onOff;
|
||||
}
|
||||
|
||||
void QtStyleCodeFormatter::onEnter(int newState, int *indentDepth, int *savedIndentDepth) const
|
||||
@@ -820,7 +845,7 @@ void QtStyleCodeFormatter::onEnter(int newState, int *indentDepth, int *savedInd
|
||||
const Token &tk = currentToken();
|
||||
const int tokenPosition = tk.begin();
|
||||
const bool firstToken = (tokenIndex() == 0);
|
||||
const bool lastToken = (tokenIndexFromEnd() == 0);
|
||||
const bool lastToken = (tokenIndex() == tokenCount() - 1);
|
||||
|
||||
switch (newState) {
|
||||
case namespace_start:
|
||||
@@ -874,28 +899,58 @@ void QtStyleCodeFormatter::onEnter(int newState, int *indentDepth, int *savedInd
|
||||
break;
|
||||
|
||||
case member_init_open:
|
||||
// undo the continuation indent of the parent
|
||||
*savedIndentDepth = parentState.savedIndentDepth;
|
||||
|
||||
if (firstToken)
|
||||
*indentDepth = tokenPosition + tk.length() + 1;
|
||||
else
|
||||
*indentDepth += m_indentSize;
|
||||
*indentDepth = *savedIndentDepth + m_indentSize;
|
||||
break;
|
||||
|
||||
case defun_open:
|
||||
case class_open:
|
||||
case case_cont:
|
||||
*indentDepth += m_indentSize;
|
||||
break;
|
||||
|
||||
case substatement_open:
|
||||
if (m_style == WhitesmithsStyle)
|
||||
break;
|
||||
if (parentState.type != switch_statement)
|
||||
case class_open:
|
||||
case enum_open:
|
||||
case defun_open:
|
||||
// undo the continuation indent of the parent
|
||||
*savedIndentDepth = parentState.savedIndentDepth;
|
||||
|
||||
if (firstToken)
|
||||
*savedIndentDepth = tokenPosition;
|
||||
|
||||
*indentDepth = *savedIndentDepth;
|
||||
|
||||
if (m_indentDeclarationMembers)
|
||||
*indentDepth += m_indentSize;
|
||||
break;
|
||||
|
||||
case substatement_open:
|
||||
if (firstToken) {
|
||||
*savedIndentDepth = tokenPosition;
|
||||
*indentDepth = *savedIndentDepth;
|
||||
} else if (m_indentSubstatementBraces && !m_indentSubstatementStatements) {
|
||||
// ### The preceding check is quite arbitrary.
|
||||
// It actually needs another flag to determine whether the closing curly
|
||||
// should be indented or not
|
||||
*indentDepth = *savedIndentDepth += m_indentSize;
|
||||
}
|
||||
|
||||
if (m_indentSubstatementStatements) {
|
||||
if (parentState.type != switch_statement)
|
||||
*indentDepth += m_indentSize;
|
||||
}
|
||||
break;
|
||||
|
||||
case brace_list_open:
|
||||
if (parentState.type != initializer)
|
||||
*indentDepth = parentState.savedIndentDepth + m_indentSize;
|
||||
else if (lastToken) {
|
||||
*savedIndentDepth = state(1).savedIndentDepth;
|
||||
*indentDepth = *savedIndentDepth + m_indentSize;
|
||||
}
|
||||
break;
|
||||
|
||||
case block_open:
|
||||
@@ -919,9 +974,6 @@ void QtStyleCodeFormatter::onEnter(int newState, int *indentDepth, int *savedInd
|
||||
// undo the continuation indent of the parent
|
||||
*indentDepth = parentState.savedIndentDepth;
|
||||
*savedIndentDepth = *indentDepth;
|
||||
// these styles want to indent braces
|
||||
if (m_style == GnuStyle || m_style == WhitesmithsStyle)
|
||||
*savedIndentDepth += m_indentSize;
|
||||
break;
|
||||
|
||||
case maybe_else: {
|
||||
@@ -998,16 +1050,27 @@ void QtStyleCodeFormatter::adjustIndent(const QList<CPlusPlus::Token> &tokens, i
|
||||
}
|
||||
break;
|
||||
case T_LBRACE: {
|
||||
if (topState.type == case_cont) {
|
||||
*indentDepth = topState.savedIndentDepth;
|
||||
// function definition - argument list is expression state
|
||||
if (topState.type == case_cont)
|
||||
*indentDepth = topState.savedIndentDepth;
|
||||
else if (topState.type == expression && previousState.type == declaration_start)
|
||||
} else if (topState.type == expression && previousState.type == declaration_start) {
|
||||
*indentDepth = previousState.savedIndentDepth;
|
||||
else if (topState.type != defun_open
|
||||
&& topState.type != substatement_open
|
||||
&& topState.type != block_open
|
||||
&& !topWasMaybeElse)
|
||||
if (m_indentDeclarationBraces)
|
||||
*indentDepth += m_indentSize;
|
||||
} else if (topState.type == class_start) {
|
||||
*indentDepth = topState.savedIndentDepth;
|
||||
if (m_indentDeclarationBraces)
|
||||
*indentDepth += m_indentSize;
|
||||
} else if (topState.type == substatement) {
|
||||
*indentDepth = topState.savedIndentDepth;
|
||||
if (m_indentSubstatementBraces)
|
||||
*indentDepth += m_indentSize;
|
||||
} else if (topState.type != defun_open
|
||||
&& topState.type != block_open
|
||||
&& !topWasMaybeElse) {
|
||||
*indentDepth = topState.savedIndentDepth;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case T_RBRACE: {
|
||||
@@ -1022,7 +1085,8 @@ void QtStyleCodeFormatter::adjustIndent(const QList<CPlusPlus::Token> &tokens, i
|
||||
|| type == class_open
|
||||
|| type == brace_list_open
|
||||
|| type == namespace_open
|
||||
|| type == block_open) {
|
||||
|| type == block_open
|
||||
|| type == enum_open) {
|
||||
*indentDepth = state(i).savedIndentDepth;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -28,9 +28,8 @@ public:
|
||||
CodeFormatter();
|
||||
virtual ~CodeFormatter();
|
||||
|
||||
void setDocument(QTextDocument *document);
|
||||
|
||||
int indentFor(const QTextBlock &block);
|
||||
void invalidateCache(QTextDocument *document);
|
||||
|
||||
protected:
|
||||
virtual void onEnter(int newState, int *indentDepth, int *savedIndentDepth) const = 0;
|
||||
@@ -58,7 +57,8 @@ protected:
|
||||
member_init_open, // After ':' that starts a member initialization list.
|
||||
|
||||
enum_start, // After 'enum'
|
||||
brace_list_open, // Open brace of an enum or static array list.
|
||||
enum_open, // Brace that opens a enum declaration.
|
||||
brace_list_open, // Open brace nested inside an enum or for a static array list.
|
||||
|
||||
namespace_start, // after the namespace token, before the opening brace.
|
||||
namespace_open, // Brace that opens a C++ namespace block.
|
||||
@@ -125,15 +125,14 @@ protected:
|
||||
};
|
||||
|
||||
State state(int belowTop = 0) const;
|
||||
const QVector<State> &newStatesThisLine() const;
|
||||
int tokenIndex() const;
|
||||
int tokenIndexFromEnd() const;
|
||||
int tokenCount() const;
|
||||
const CPlusPlus::Token ¤tToken() const;
|
||||
const CPlusPlus::Token &tokenAt(int idx) const;
|
||||
|
||||
bool isBracelessState(int type) const;
|
||||
|
||||
void invalidateCache();
|
||||
|
||||
private:
|
||||
void requireStatesUntil(const QTextBlock &block);
|
||||
void recalculateStateAfter(const QTextBlock &block);
|
||||
@@ -159,10 +158,9 @@ private:
|
||||
private:
|
||||
static QStack<State> initialState();
|
||||
|
||||
QPointer<QTextDocument> m_document;
|
||||
|
||||
QStack<State> m_beginState;
|
||||
QStack<State> m_currentState;
|
||||
QStack<State> m_newStates;
|
||||
|
||||
QList<CPlusPlus::Token> m_tokens;
|
||||
QString m_currentLine;
|
||||
@@ -182,12 +180,10 @@ public:
|
||||
|
||||
void setIndentSize(int size);
|
||||
|
||||
enum CompoundStyle {
|
||||
QtStyle, // don't indent braces, add indent for contained statements
|
||||
WhitesmithsStyle, // add indent for braces, don't for the contained statements
|
||||
GnuStyle // add indent for braces and again for contained statements
|
||||
};
|
||||
void setCompoundStyle(CompoundStyle style);
|
||||
void setIndentSubstatementBraces(bool onOff);
|
||||
void setIndentSubstatementStatements(bool onOff);
|
||||
void setIndentDeclarationBraces(bool onOff);
|
||||
void setIndentDeclarationMembers(bool onOff);
|
||||
|
||||
protected:
|
||||
virtual void onEnter(int newState, int *indentDepth, int *savedIndentDepth) const;
|
||||
@@ -195,7 +191,10 @@ protected:
|
||||
|
||||
private:
|
||||
int m_indentSize;
|
||||
CompoundStyle m_style;
|
||||
bool m_indentSubstatementBraces;
|
||||
bool m_indentSubstatementStatements;
|
||||
bool m_indentDeclarationBraces;
|
||||
bool m_indentDeclarationMembers;
|
||||
};
|
||||
|
||||
} // namespace CppTools
|
||||
|
||||
Reference in New Issue
Block a user