Commit 88f2e340 authored by Christian Kamm's avatar Christian Kamm

C++: Introduce the new CodeFormatter.

Done-with: Erik Verbruggen
parent 837e7b5a
This diff is collapsed.
#ifndef CPPCODEFORMATTER_H
#define CPPCODEFORMATTER_H
#include "cpptools_global.h"
#include <cplusplus/SimpleLexer.h>
#include <Token.h>
#include <QtCore/QChar>
#include <QtCore/QStack>
#include <QtCore/QList>
#include <QtCore/QVector>
#include <QtCore/QPointer>
QT_BEGIN_NAMESPACE
class QTextDocument;
class QTextBlock;
QT_END_NAMESPACE
namespace CppTools {
namespace Internal {
class CppCodeFormatterData;
}
class CPPTOOLS_EXPORT CodeFormatter
{
public:
CodeFormatter();
virtual ~CodeFormatter();
void setDocument(QTextDocument *document);
int indentFor(const QTextBlock &block);
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;
protected:
enum StateType {
invalid = 0,
topmost_intro, // The first line in a "topmost" definition.
multiline_comment_start, // Inside the first line of a multi-line C style block comment.
multiline_comment_cont, // Inside the following lines of a multi-line C style block comment.
cpp_macro_start, // After the '#' token
cpp_macro, // The start of a C preprocessor macro definition.
cpp_macro_cont, // Subsequent lines of a multi-line C preprocessor macro definition.
cpp_macro_conditional, // Special marker used for separating saved from current state when dealing with #ifdef
qt_like_macro, // after an identifier starting with Q_ or QT_ at the beginning of the line
defun_open, // Brace that opens a top-level function definition.
using_start, // right after the "using" token
class_start, // after the 'class' token
class_open, // Brace that opens a class definition.
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.
namespace_start, // after the namespace token, before the opening brace.
namespace_open, // Brace that opens a C++ namespace block.
declaration_start, // shifted a token which could start a declaration.
operator_declaration, // after 'operator' in declaration_start
template_start, // after the 'template' token
template_param, // after the '<' in a template_start
if_statement, // After 'if'
maybe_else, // after the first substatement in an if
else_clause, // The else line of an if-else construct.
for_statement, // After the 'for' token
for_statement_paren_open, // While inside the (...)
for_statement_init, // The initializer part of the for statement
for_statement_condition, // The condition part of the for statement
for_statement_expression, // The expression part of the for statement
switch_statement, // After 'switch' token
case_start, // after a 'case' or 'default' token
case_cont, // after the colon in a case/default
statement_with_condition, // A statement that takes a condition after the start token.
do_statement, // After 'do' token
return_statement, // After 'return'
block_open, // Statement block open brace.
substatement, // The first line after a conditional or loop construct.
substatement_open, // The brace that opens a substatement block.
arglist_open, // after the lparen. TODO: check if this is enough.
stream_op, // Lines continuing a stream operator (C++ only).
ternary_op, // The ? : operator
condition_open, // Start of a condition in 'if', 'while', entered after opening paren
condition_paren_open, // After an lparen in a condition
assign_open, // after an assignment token
expression, // after a '=' in a declaration_start once we're sure it's not '= {'
initializer, // after a '=' in a declaration start
};
struct State {
State()
: savedIndentDepth(0)
, type(0)
{}
State(quint8 ty, quint16 savedDepth)
: savedIndentDepth(savedDepth)
, type(ty)
{}
quint16 savedIndentDepth;
quint8 type;
bool operator==(const State &other) const {
return type == other.type
&& savedIndentDepth == other.savedIndentDepth;
}
};
State state(int belowTop = 0) const;
int tokenIndex() const;
int tokenIndexFromEnd() const;
const CPlusPlus::Token &currentToken() 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);
void storeBlockState(const QTextBlock &block);
void restoreBlockState(const QTextBlock &block);
QStringRef currentTokenText() const;
int tokenizeBlock(const QTextBlock &block, bool *endedJoined = 0);
void turnInto(int newState);
bool tryExpression(bool alsoExpression = false);
bool tryDeclaration();
bool tryStatement();
void enter(int newState);
void leave(bool statementDone = false);
void correctIndentation(const QTextBlock &block);
void dump();
private:
static QStack<State> initialState();
QPointer<QTextDocument> m_document;
QStack<State> m_beginState;
QStack<State> m_currentState;
QList<CPlusPlus::Token> m_tokens;
QString m_currentLine;
CPlusPlus::Token m_currentToken;
int m_tokenIndex;
// should store indent level and padding instead
int m_indentDepth;
friend class Internal::CppCodeFormatterData;
};
class CPPTOOLS_EXPORT QtStyleCodeFormatter : public CodeFormatter
{
public:
QtStyleCodeFormatter();
void setIndentSize(int size);
protected:
virtual void onEnter(int newState, int *indentDepth, int *savedIndentDepth) const;
virtual void adjustIndent(const QList<CPlusPlus::Token> &tokens, int lexerState, int *indentDepth) const;
private:
int m_indentSize;
};
} // namespace CppTools
#endif // CPPCODEFORMATTER_H
...@@ -23,7 +23,8 @@ HEADERS += completionsettingspage.h \ ...@@ -23,7 +23,8 @@ HEADERS += completionsettingspage.h \
searchsymbols.h \ searchsymbols.h \
cppdoxygen.h \ cppdoxygen.h \
cppfilesettingspage.h \ cppfilesettingspage.h \
cppfindreferences.h cppfindreferences.h \
cppcodeformatter.h
SOURCES += completionsettingspage.cpp \ SOURCES += completionsettingspage.cpp \
cppclassesfilter.cpp \ cppclassesfilter.cpp \
...@@ -38,7 +39,8 @@ SOURCES += completionsettingspage.cpp \ ...@@ -38,7 +39,8 @@ SOURCES += completionsettingspage.cpp \
cppdoxygen.cpp \ cppdoxygen.cpp \
cppfilesettingspage.cpp \ cppfilesettingspage.cpp \
abstracteditorsupport.cpp \ abstracteditorsupport.cpp \
cppfindreferences.cpp cppfindreferences.cpp \
cppcodeformatter.cpp
FORMS += completionsettingspage.ui \ FORMS += completionsettingspage.ui \
cppfilesettingspage.ui cppfilesettingspage.ui
......
...@@ -31,6 +31,15 @@ ...@@ -31,6 +31,15 @@
using namespace TextEditor; using namespace TextEditor;
CodeFormatterData::CodeFormatterData(int blockRevision)
: m_blockRevision(blockRevision)
{
}
CodeFormatterData::~CodeFormatterData()
{
}
TextBlockUserData::~TextBlockUserData() TextBlockUserData::~TextBlockUserData()
{ {
TextMarks marks = m_marks; TextMarks marks = m_marks;
...@@ -38,6 +47,9 @@ TextBlockUserData::~TextBlockUserData() ...@@ -38,6 +47,9 @@ TextBlockUserData::~TextBlockUserData()
foreach (ITextMark *mrk, marks) { foreach (ITextMark *mrk, marks) {
mrk->removedFromEditor(); mrk->removedFromEditor();
} }
if (m_codeFormatterData)
delete m_codeFormatterData;
} }
int TextBlockUserData::braceDepthDelta() const int TextBlockUserData::braceDepthDelta() const
...@@ -359,6 +371,35 @@ TextBlockUserData::MatchType TextBlockUserData::matchCursorForward(QTextCursor * ...@@ -359,6 +371,35 @@ TextBlockUserData::MatchType TextBlockUserData::matchCursorForward(QTextCursor *
return NoMatch; return NoMatch;
} }
int TextBlockUserData::lexerState(const QTextBlock &block)
{
if (!block.isValid())
return -1;
int data = block.userState();
if (data == -1)
return -1;
return data & 0xFF;
}
void TextBlockUserData::setLexerState(QTextBlock block, int state)
{
if (!block.isValid())
return;
int data = block.userState();
if (data == -1)
data = 0;
block.setUserState((data & ~0xFF) | (state & 0xFF));
}
void TextBlockUserData::setCodeFormatterData(CodeFormatterData *data)
{
if (m_codeFormatterData)
delete m_codeFormatterData;
m_codeFormatterData = data;
}
BaseTextDocumentLayout::BaseTextDocumentLayout(QTextDocument *doc) BaseTextDocumentLayout::BaseTextDocumentLayout(QTextDocument *doc)
:QPlainTextDocumentLayout(doc) { :QPlainTextDocumentLayout(doc) {
...@@ -528,6 +569,3 @@ QSizeF BaseTextDocumentLayout::documentSize() const ...@@ -528,6 +569,3 @@ QSizeF BaseTextDocumentLayout::documentSize() const
size.setWidth(qMax((qreal)m_requiredWidth, size.width())); size.setWidth(qMax((qreal)m_requiredWidth, size.width()));
return size; return size;
} }
...@@ -54,6 +54,18 @@ struct TEXTEDITOR_EXPORT Parenthesis ...@@ -54,6 +54,18 @@ struct TEXTEDITOR_EXPORT Parenthesis
int pos; int pos;
}; };
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 class TEXTEDITOR_EXPORT TextBlockUserData : public QTextBlockUserData
{ {
...@@ -64,7 +76,9 @@ public: ...@@ -64,7 +76,9 @@ public:
m_ifdefedOut(false), m_ifdefedOut(false),
m_foldingIndent(0), m_foldingIndent(0),
m_foldingStartIncluded(false), m_foldingStartIncluded(false),
m_foldingEndIncluded(false){} m_foldingEndIncluded(false),
m_codeFormatterData(0)
{}
~TextBlockUserData(); ~TextBlockUserData();
inline TextMarks marks() const { return m_marks; } inline TextMarks marks() const { return m_marks; }
...@@ -106,6 +120,11 @@ public: ...@@ -106,6 +120,11 @@ public:
void setFoldingEndIncluded(bool included) { m_foldingEndIncluded = included; } void setFoldingEndIncluded(bool included) { m_foldingEndIncluded = included; }
bool foldingEndIncluded() const { return m_foldingEndIncluded; } bool foldingEndIncluded() const { return m_foldingEndIncluded; }
static int lexerState(const QTextBlock &block);
static void setLexerState(QTextBlock block, int state);
CodeFormatterData *codeFormatterData() const { return m_codeFormatterData; }
void setCodeFormatterData(CodeFormatterData *data);
private: private:
TextMarks m_marks; TextMarks m_marks;
...@@ -115,6 +134,7 @@ private: ...@@ -115,6 +134,7 @@ private:
uint m_foldingStartIncluded : 1; uint m_foldingStartIncluded : 1;
uint m_foldingEndIncluded : 1; uint m_foldingEndIncluded : 1;
Parentheses m_parentheses; Parentheses m_parentheses;
CodeFormatterData *m_codeFormatterData;
}; };
......
TEMPLATE = app
CONFIG += qt warn_on console depend_includepath
QT += testlib
include(../shared/shared.pri)
SRCDIR = ../../../../src
SOURCES += \
tst_codeformatter.cpp \
$$SRCDIR/plugins/cpptools/cppcodeformatter.cpp \
$$SRCDIR/plugins/texteditor/basetextdocumentlayout.cpp
HEADERS += \
$$SRCDIR/plugins/texteditor/basetextdocumentlayout.h
INCLUDEPATH += $$SRCDIR/plugins $$SRCDIR/libs
TARGET=tst_$$TARGET
This diff is collapsed.
TEMPLATE = subdirs TEMPLATE = subdirs
SUBDIRS = shared ast semantic lookup preprocessor findusages typeprettyprinter SUBDIRS = shared ast semantic lookup preprocessor findusages typeprettyprinter codeformatter
CONFIG += ordered CONFIG += ordered
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment