forked from qt-creator/qt-creator
C++: Introduce the new CodeFormatter.
Done-with: Erik Verbruggen
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,195 @@
|
||||
#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 ¤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);
|
||||
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 \
|
||||
searchsymbols.h \
|
||||
cppdoxygen.h \
|
||||
cppfilesettingspage.h \
|
||||
cppfindreferences.h
|
||||
cppfindreferences.h \
|
||||
cppcodeformatter.h
|
||||
|
||||
SOURCES += completionsettingspage.cpp \
|
||||
cppclassesfilter.cpp \
|
||||
@@ -38,7 +39,8 @@ SOURCES += completionsettingspage.cpp \
|
||||
cppdoxygen.cpp \
|
||||
cppfilesettingspage.cpp \
|
||||
abstracteditorsupport.cpp \
|
||||
cppfindreferences.cpp
|
||||
cppfindreferences.cpp \
|
||||
cppcodeformatter.cpp
|
||||
|
||||
FORMS += completionsettingspage.ui \
|
||||
cppfilesettingspage.ui
|
||||
|
||||
@@ -31,6 +31,15 @@
|
||||
|
||||
using namespace TextEditor;
|
||||
|
||||
CodeFormatterData::CodeFormatterData(int blockRevision)
|
||||
: m_blockRevision(blockRevision)
|
||||
{
|
||||
}
|
||||
|
||||
CodeFormatterData::~CodeFormatterData()
|
||||
{
|
||||
}
|
||||
|
||||
TextBlockUserData::~TextBlockUserData()
|
||||
{
|
||||
TextMarks marks = m_marks;
|
||||
@@ -38,6 +47,9 @@ TextBlockUserData::~TextBlockUserData()
|
||||
foreach (ITextMark *mrk, marks) {
|
||||
mrk->removedFromEditor();
|
||||
}
|
||||
|
||||
if (m_codeFormatterData)
|
||||
delete m_codeFormatterData;
|
||||
}
|
||||
|
||||
int TextBlockUserData::braceDepthDelta() const
|
||||
@@ -359,6 +371,35 @@ TextBlockUserData::MatchType TextBlockUserData::matchCursorForward(QTextCursor *
|
||||
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)
|
||||
:QPlainTextDocumentLayout(doc) {
|
||||
@@ -528,6 +569,3 @@ QSizeF BaseTextDocumentLayout::documentSize() const
|
||||
size.setWidth(qMax((qreal)m_requiredWidth, size.width()));
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -54,6 +54,18 @@ struct TEXTEDITOR_EXPORT Parenthesis
|
||||
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
|
||||
{
|
||||
@@ -64,7 +76,9 @@ public:
|
||||
m_ifdefedOut(false),
|
||||
m_foldingIndent(0),
|
||||
m_foldingStartIncluded(false),
|
||||
m_foldingEndIncluded(false){}
|
||||
m_foldingEndIncluded(false),
|
||||
m_codeFormatterData(0)
|
||||
{}
|
||||
~TextBlockUserData();
|
||||
|
||||
inline TextMarks marks() const { return m_marks; }
|
||||
@@ -106,6 +120,11 @@ public:
|
||||
void setFoldingEndIncluded(bool included) { m_foldingEndIncluded = included; }
|
||||
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:
|
||||
TextMarks m_marks;
|
||||
@@ -115,6 +134,7 @@ private:
|
||||
uint m_foldingStartIncluded : 1;
|
||||
uint m_foldingEndIncluded : 1;
|
||||
Parentheses m_parentheses;
|
||||
CodeFormatterData *m_codeFormatterData;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
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
|
||||
@@ -0,0 +1,695 @@
|
||||
#include <QtTest>
|
||||
#include <QObject>
|
||||
#include <QList>
|
||||
#include <QTextDocument>
|
||||
#include <QTextBlock>
|
||||
|
||||
#include <cpptools/cppcodeformatter.h>
|
||||
using namespace CppTools;
|
||||
|
||||
class tst_CodeFormatter: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private Q_SLOTS:
|
||||
void ifStatementWithoutBraces1();
|
||||
void ifStatementWithoutBraces2();
|
||||
void ifStatementWithBraces1();
|
||||
void ifStatementWithBraces2();
|
||||
void ifStatementMixed();
|
||||
void ifStatementAndComments();
|
||||
void ifStatementLongCondition();
|
||||
void strayElse();
|
||||
void macrosNoSemicolon();
|
||||
void oneLineIf();
|
||||
void doWhile();
|
||||
void closingCurlies();
|
||||
void ifdefedInsideIf();
|
||||
void ifdefs();
|
||||
void preprocessorContinuation();
|
||||
void cStyleComments();
|
||||
void cppStyleComments();
|
||||
void expressionContinuation();
|
||||
void classAccess();
|
||||
void ternary();
|
||||
void objcAtDeclarations();
|
||||
void braceList();
|
||||
void bug1();
|
||||
void bug2();
|
||||
void switch1();
|
||||
void memberInitializer();
|
||||
void templates();
|
||||
void operatorOverloads();
|
||||
};
|
||||
|
||||
struct Line {
|
||||
Line(QString l)
|
||||
: line(l)
|
||||
{
|
||||
for (int i = 0; i < l.size(); ++i) {
|
||||
if (!l.at(i).isSpace()) {
|
||||
expectedIndent = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
expectedIndent = l.size();
|
||||
}
|
||||
|
||||
Line(QString l, int expect)
|
||||
: line(l), expectedIndent(expect)
|
||||
{}
|
||||
|
||||
QString line;
|
||||
int expectedIndent;
|
||||
};
|
||||
|
||||
QString concatLines(QList<Line> lines)
|
||||
{
|
||||
QString result;
|
||||
foreach (const Line &l, lines) {
|
||||
result += l.line;
|
||||
result += "\n";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void checkIndent(QList<Line> data)
|
||||
{
|
||||
QString text = concatLines(data);
|
||||
QTextDocument document(text);
|
||||
QtStyleCodeFormatter formatter;
|
||||
formatter.setDocument(&document);
|
||||
|
||||
int i = 0;
|
||||
foreach (const Line &l, data) {
|
||||
if (l.expectedIndent != -1) {
|
||||
int actualIndent = formatter.indentFor(document.findBlockByLineNumber(i));
|
||||
if (actualIndent != l.expectedIndent) {
|
||||
QFAIL(QString("Wrong indent in line %1 with text '%2', expected indent %3, got %4").arg(
|
||||
QString::number(i+1), l.line, QString::number(l.expectedIndent), QString::number(actualIndent)).toLatin1().constData());
|
||||
}
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
void tst_CodeFormatter::ifStatementWithoutBraces1()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("void foo() {")
|
||||
<< Line(" if (a)")
|
||||
<< Line(" if (b)")
|
||||
<< Line(" foo;")
|
||||
<< Line(" else if (c)")
|
||||
<< Line(" foo;")
|
||||
<< Line(" else")
|
||||
<< Line(" if (d)")
|
||||
<< Line(" foo;")
|
||||
<< Line(" else")
|
||||
<< Line(" while (e)")
|
||||
<< Line(" bar;")
|
||||
<< Line(" else")
|
||||
<< Line(" foo;")
|
||||
<< Line("}")
|
||||
;
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_CodeFormatter::ifStatementWithoutBraces2()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("void foo() {")
|
||||
<< Line(" if (a)")
|
||||
<< Line(" if (b)")
|
||||
<< Line(" foo;")
|
||||
<< Line(" if (a) b();")
|
||||
<< Line(" if (a) b(); else")
|
||||
<< Line(" foo;")
|
||||
<< Line(" if (a)")
|
||||
<< Line(" if (b)")
|
||||
<< Line(" foo;")
|
||||
<< Line(" else if (c)")
|
||||
<< Line(" foo;")
|
||||
<< Line(" else")
|
||||
<< Line(" if (d)")
|
||||
<< Line(" foo;")
|
||||
<< Line(" else")
|
||||
<< Line(" while (e)")
|
||||
<< Line(" bar;")
|
||||
<< Line(" else")
|
||||
<< Line(" foo;")
|
||||
<< Line("}")
|
||||
;
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_CodeFormatter::ifStatementWithBraces1()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("void foo() {")
|
||||
<< Line(" if (a) {")
|
||||
<< Line(" if (b) {")
|
||||
<< Line(" foo;")
|
||||
<< Line(" } else if (c) {")
|
||||
<< Line(" foo;")
|
||||
<< Line(" } else {")
|
||||
<< Line(" if (d) {")
|
||||
<< Line(" foo;")
|
||||
<< Line(" } else {")
|
||||
<< Line(" foo;")
|
||||
<< Line(" }")
|
||||
<< Line(" }")
|
||||
<< Line(" } else {")
|
||||
<< Line(" foo;")
|
||||
<< Line(" }")
|
||||
<< Line("}");
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_CodeFormatter::ifStatementWithBraces2()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("void foo()")
|
||||
<< Line("{")
|
||||
<< Line(" if (a)")
|
||||
<< Line(" {")
|
||||
<< Line(" if (b)")
|
||||
<< Line(" {")
|
||||
<< Line(" foo;")
|
||||
<< Line(" }")
|
||||
<< Line(" else if (c)")
|
||||
<< Line(" {")
|
||||
<< Line(" foo;")
|
||||
<< Line(" }")
|
||||
<< Line(" else")
|
||||
<< Line(" {")
|
||||
<< Line(" if (d)")
|
||||
<< Line(" {")
|
||||
<< Line(" foo;")
|
||||
<< Line(" }")
|
||||
<< Line(" else")
|
||||
<< Line(" {")
|
||||
<< Line(" foo;")
|
||||
<< Line(" }")
|
||||
<< Line(" }")
|
||||
<< Line(" }")
|
||||
<< Line(" else")
|
||||
<< Line(" {")
|
||||
<< Line(" foo;")
|
||||
<< Line(" }")
|
||||
<< Line("}");
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_CodeFormatter::ifStatementMixed()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("void foo()")
|
||||
<< Line("{")
|
||||
<< Line(" if (foo)")
|
||||
<< Line(" if (bar)")
|
||||
<< Line(" {")
|
||||
<< Line(" foo;")
|
||||
<< Line(" }")
|
||||
<< Line(" else")
|
||||
<< Line(" if (car)")
|
||||
<< Line(" {}")
|
||||
<< Line(" else doo;")
|
||||
<< Line(" else abc;")
|
||||
<< Line("}");
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_CodeFormatter::ifStatementAndComments()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("void foo()")
|
||||
<< Line("{")
|
||||
<< Line(" if (foo)")
|
||||
<< Line(" ; // bla")
|
||||
<< Line(" else if (bar)")
|
||||
<< Line(" ;")
|
||||
<< Line(" if (foo)")
|
||||
<< Line(" ; /* bla")
|
||||
<< Line(" bla */")
|
||||
<< Line(" else if (bar)")
|
||||
<< Line(" // foobar")
|
||||
<< Line(" ;")
|
||||
<< Line(" else if (bar)")
|
||||
<< Line(" /* bla")
|
||||
<< Line(" bla */")
|
||||
<< Line(" ;")
|
||||
<< Line("}");
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_CodeFormatter::ifStatementLongCondition()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("void foo()")
|
||||
<< Line("{")
|
||||
<< Line(" if (foo &&")
|
||||
<< Line(" bar")
|
||||
<< Line(" || (a + b > 4")
|
||||
<< Line(" && foo(bar)")
|
||||
<< Line(" )")
|
||||
<< Line(" ) {")
|
||||
<< Line(" foo;")
|
||||
<< Line(" }")
|
||||
<< Line("}");
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_CodeFormatter::strayElse()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("void foo()")
|
||||
<< Line("{")
|
||||
<< Line(" while( true ) {}")
|
||||
<< Line(" else", -1)
|
||||
<< Line(" else {", -1)
|
||||
<< Line(" }", -1)
|
||||
<< Line("}");
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_CodeFormatter::macrosNoSemicolon()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("QT_DECLARE_METATYPE(foo)")
|
||||
<< Line("int i;")
|
||||
<< Line("Q_BLABLA")
|
||||
<< Line("int i;")
|
||||
<< Line("Q_BLABLA;")
|
||||
<< Line("int i;")
|
||||
<< Line("Q_BLABLA();")
|
||||
<< Line("int i;")
|
||||
<< Line("Q_PROPERTY(abc)")
|
||||
<< Line("QDOC_PROPERTY(abc)")
|
||||
<< Line("void foo() {")
|
||||
<< Line(" QT_DECLARE_METATYPE(foo)")
|
||||
<< Line(" int i;")
|
||||
<< Line(" Q_BLABLA")
|
||||
<< Line(" int i;")
|
||||
<< Line(" Q_BLABLA;")
|
||||
<< Line(" int i;")
|
||||
<< Line(" Q_BLABLA();")
|
||||
<< Line(" Q_PROPERTY(abc)")
|
||||
<< Line(" QDOC_PROPERTY(abc)")
|
||||
<< Line(" int i;")
|
||||
<< Line("}")
|
||||
;
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_CodeFormatter::oneLineIf()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("class F {")
|
||||
<< Line(" void foo()")
|
||||
<< Line(" { if (showIt) show(); }")
|
||||
<< Line("};")
|
||||
;
|
||||
checkIndent(data);
|
||||
|
||||
}
|
||||
|
||||
void tst_CodeFormatter::doWhile()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("void foo() {")
|
||||
<< Line(" do { if (c) foo; } while(a);")
|
||||
<< Line(" do {")
|
||||
<< Line(" if(a);")
|
||||
<< Line(" } while(a);")
|
||||
<< Line(" do")
|
||||
<< Line(" foo;")
|
||||
<< Line(" while(a);")
|
||||
<< Line(" do foo; while(a);")
|
||||
<< Line("};")
|
||||
;
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_CodeFormatter::closingCurlies()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("void foo() {")
|
||||
<< Line(" if (a)")
|
||||
<< Line(" if (b) {")
|
||||
<< Line(" foo;")
|
||||
<< Line(" }")
|
||||
<< Line(" {")
|
||||
<< Line(" foo();")
|
||||
<< Line(" }")
|
||||
<< Line(" foo();")
|
||||
<< Line(" {")
|
||||
<< Line(" foo();")
|
||||
<< Line(" }")
|
||||
<< Line(" while (a) {")
|
||||
<< Line(" if (a);")
|
||||
<< Line(" }")
|
||||
<< Line("};")
|
||||
;
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_CodeFormatter::ifdefedInsideIf()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("void foo() {")
|
||||
<< Line(" if (a) {")
|
||||
<< Line("#ifndef Q_WS_WINCE")
|
||||
<< Line(" if (b) {")
|
||||
<< Line("#else")
|
||||
<< Line(" if (c) {")
|
||||
<< Line("#endif")
|
||||
<< Line(" }")
|
||||
<< Line(" } else if (d) {")
|
||||
<< Line(" }")
|
||||
<< Line(" if (a)")
|
||||
<< Line(" ;")
|
||||
<< Line(" else if (type == Qt::Dialog || type == Qt::Sheet)")
|
||||
<< Line("#ifndef Q_WS_WINCE")
|
||||
<< Line(" flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowContextHelpButtonHint | Qt::WindowCloseButtonHint;")
|
||||
<< Line("#else")
|
||||
<< Line(" bar;")
|
||||
<< Line("#endif")
|
||||
<< Line("};")
|
||||
;
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_CodeFormatter::ifdefs()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("#ifdef FOO")
|
||||
<< Line("#include <bar>")
|
||||
<< Line("void foo()")
|
||||
<< Line("{")
|
||||
<< Line(" if (bar)")
|
||||
<< Line("#if 1")
|
||||
<< Line(" foo;")
|
||||
<< Line(" else")
|
||||
<< Line("#endif")
|
||||
<< Line(" foo;")
|
||||
<< Line("}")
|
||||
<< Line("#endif")
|
||||
;
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_CodeFormatter::preprocessorContinuation()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("#define x \\")
|
||||
<< Line(" foo(x) + \\")
|
||||
<< Line(" bar(x)")
|
||||
<< Line("int i;")
|
||||
<< Line("void foo() {")
|
||||
<< Line("#define y y")
|
||||
<< Line("#define x \\")
|
||||
<< Line(" foo(x) + \\")
|
||||
<< Line(" bar(x)")
|
||||
<< Line(" int j;")
|
||||
<< Line("};")
|
||||
;
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_CodeFormatter::cStyleComments()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("/*")
|
||||
<< Line(" ")
|
||||
<< Line(" foo")
|
||||
<< Line(" ")
|
||||
<< Line(" foo")
|
||||
<< Line(" ")
|
||||
<< Line("*/")
|
||||
<< Line("void foo() {")
|
||||
<< Line(" /*")
|
||||
<< Line(" ")
|
||||
<< Line(" foo")
|
||||
<< Line(" ")
|
||||
<< Line(" */")
|
||||
<< Line(" /* bar */")
|
||||
<< Line("}")
|
||||
<< Line("struct s {")
|
||||
<< Line(" /* foo */")
|
||||
<< Line(" /*")
|
||||
<< Line(" ")
|
||||
<< Line(" foo")
|
||||
<< Line(" ")
|
||||
<< Line(" */")
|
||||
<< Line(" /* bar */")
|
||||
;
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_CodeFormatter::cppStyleComments()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("// abc")
|
||||
<< Line("class C { ")
|
||||
<< Line(" // ghij")
|
||||
<< Line(" // def")
|
||||
<< Line(" // ghij")
|
||||
<< Line(" int i; // hik")
|
||||
<< Line(" // doo")
|
||||
<< Line("} // ba")
|
||||
<< Line("// ba")
|
||||
;
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_CodeFormatter::expressionContinuation()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("void foo() {")
|
||||
<< Line(" return (a <= b &&")
|
||||
<< Line(" c <= d);")
|
||||
<< Line(" return (qMax <= qMin() &&")
|
||||
<< Line(" qMax(r1.top(), r2.top()) <= qMin(r1.bottom(), r2.bottom()));")
|
||||
<< Line(" return a")
|
||||
<< Line(" == b && c == d;")
|
||||
<< Line(" return a ==")
|
||||
<< Line(" b && c == d;")
|
||||
<< Line(" return a == b")
|
||||
<< Line(" && c == d;")
|
||||
<< Line(" return a == b &&")
|
||||
<< Line(" c == d;")
|
||||
<< Line(" return a == b && c")
|
||||
<< Line(" == d;")
|
||||
<< Line(" return a == b && c ==")
|
||||
<< Line(" d;")
|
||||
<< Line(" return a == b && c == d;")
|
||||
<< Line(" qDebug() << foo")
|
||||
<< Line(" << bar << moose")
|
||||
<< Line(" << bar +")
|
||||
<< Line(" foo - blah(1)")
|
||||
<< Line(" << '?'")
|
||||
<< Line(" << \"\\n\";")
|
||||
<< Line(" i += foo(")
|
||||
<< Line(" bar,")
|
||||
<< Line(" 2);")
|
||||
<< Line("}")
|
||||
;
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_CodeFormatter::classAccess()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("class foo {")
|
||||
<< Line(" int i;")
|
||||
<< Line("public:")
|
||||
<< Line(" class bar {")
|
||||
<< Line(" private:")
|
||||
<< Line(" int i;")
|
||||
<< Line(" public:")
|
||||
<< Line(" private slots:")
|
||||
<< Line(" void foo();")
|
||||
<< Line(" public Q_SLOTS:")
|
||||
<< Line(" Q_SIGNALS:")
|
||||
<< Line(" };")
|
||||
<< Line(" float f;")
|
||||
<< Line("private:")
|
||||
<< Line(" void bar(){}")
|
||||
<< Line("}")
|
||||
;
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_CodeFormatter::ternary()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("void foo() {")
|
||||
<< Line(" int i = a ? b : c;")
|
||||
<< Line(" foo += a_bigger_condition ?")
|
||||
<< Line(" b")
|
||||
<< Line(" : c;")
|
||||
<< Line(" int i = a ?")
|
||||
<< Line(" b : c;")
|
||||
<< Line(" int i = a ? b")
|
||||
<< Line(" : c +")
|
||||
<< Line(" 2;")
|
||||
<< Line(" int i = (a ? b : c) + (foo")
|
||||
<< Line(" bar);")
|
||||
<< Line("}")
|
||||
;
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_CodeFormatter::bug1()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("void foo() {")
|
||||
<< Line(" if (attribute < int(8*sizeof(uint))) {")
|
||||
<< Line(" if (on)")
|
||||
<< Line(" data->widget_attributes |= (1<<attribute);")
|
||||
<< Line(" else")
|
||||
<< Line(" data->widget_attributes &= ~(1<<attribute);")
|
||||
<< Line(" } else {")
|
||||
<< Line(" const int x = attribute - 8*sizeof(uint);")
|
||||
<< Line(" }")
|
||||
<< Line(" int i;")
|
||||
<< Line("}")
|
||||
;
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_CodeFormatter::bug2()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("void foo() {")
|
||||
<< Line(" const int sourceY = foo(")
|
||||
<< Line(" bar(")
|
||||
<< Line(" car(a,")
|
||||
<< Line(" b),")
|
||||
<< Line(" b),")
|
||||
<< Line(" foo);")
|
||||
<< Line(" const int sourceY =")
|
||||
<< Line(" foo(")
|
||||
<< Line(" bar(a,")
|
||||
<< Line(" b),")
|
||||
<< Line(" b);")
|
||||
<< Line(" int j;")
|
||||
<< Line(" const int sourceY =")
|
||||
<< Line(" (direction == DirectionEast || direction == DirectionWest) ?")
|
||||
<< Line(" (sourceRect.top() + (sourceRect.bottom() - sourceRect.top()) / 2)")
|
||||
<< Line(" : (direction == DirectionSouth ? sourceRect.bottom() : sourceRect.top());")
|
||||
<< Line("}")
|
||||
;
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_CodeFormatter::braceList()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("enum Foo {")
|
||||
<< Line(" a,")
|
||||
<< Line(" b,")
|
||||
<< Line("};")
|
||||
<< Line("void foo () {")
|
||||
<< Line(" int[] a = { foo, bar, ")
|
||||
<< Line(" car };")
|
||||
<< Line(" int k;")
|
||||
;
|
||||
checkIndent(data);
|
||||
|
||||
}
|
||||
|
||||
void tst_CodeFormatter::objcAtDeclarations()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("@class Forwarded;")
|
||||
<< Line("@protocol Forwarded;")
|
||||
<< Line("int i;")
|
||||
;
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_CodeFormatter::switch1()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("void foo() {")
|
||||
<< Line(" switch (a) {")
|
||||
<< Line(" case 1:")
|
||||
<< Line(" foo;")
|
||||
<< Line(" if (a);")
|
||||
<< Line(" case 2:")
|
||||
<< Line(" case 3: {")
|
||||
<< Line(" foo;")
|
||||
<< Line(" }")
|
||||
<< Line(" case 4:")
|
||||
<< Line(" {")
|
||||
<< Line(" foo;")
|
||||
<< Line(" }")
|
||||
<< Line(" case bar:")
|
||||
<< Line(" break;")
|
||||
<< Line(" }")
|
||||
<< Line(" case 4:")
|
||||
<< Line(" {")
|
||||
<< Line(" if (a) {")
|
||||
<< Line(" }")
|
||||
<< Line(" }")
|
||||
<< Line("}")
|
||||
;
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_CodeFormatter::memberInitializer()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("void foo()")
|
||||
<< Line(" : baR()")
|
||||
<< Line(" , m_member(23)")
|
||||
<< Line("{")
|
||||
<< Line("}")
|
||||
<< Line("class Foo {")
|
||||
<< Line(" Foo()")
|
||||
<< Line(" : baR(),")
|
||||
<< Line(" moo(barR)")
|
||||
<< Line(" {}")
|
||||
<< Line("}")
|
||||
;
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_CodeFormatter::templates()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("template <class T, typename F, int i>")
|
||||
<< Line("class Foo {")
|
||||
<< Line("private:")
|
||||
<< Line("};")
|
||||
<< Line("template <class T,")
|
||||
<< Line(" typename F, int i")
|
||||
<< Line(" >")
|
||||
<< Line("class Foo {")
|
||||
<< Line("private:")
|
||||
<< Line("};")
|
||||
;
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_CodeFormatter::operatorOverloads()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("struct S {")
|
||||
<< Line(" void operator()() {")
|
||||
<< Line(" foo;")
|
||||
<< Line(" }")
|
||||
<< Line(" void operator<<() {")
|
||||
<< Line(" foo;")
|
||||
<< Line(" }")
|
||||
<< Line("};")
|
||||
;
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
QTEST_APPLESS_MAIN(tst_CodeFormatter)
|
||||
#include "tst_codeformatter.moc"
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
TEMPLATE = subdirs
|
||||
SUBDIRS = shared ast semantic lookup preprocessor findusages typeprettyprinter
|
||||
SUBDIRS = shared ast semantic lookup preprocessor findusages typeprettyprinter codeformatter
|
||||
CONFIG += ordered
|
||||
|
||||
Reference in New Issue
Block a user