forked from qt-creator/qt-creator
Use the backward scanner to indent labeled statements, ctor-initializers and access specifiers.
This commit is contained in:
@@ -38,6 +38,7 @@ BackwardsScanner::BackwardsScanner(const QTextCursor &cursor, const QString &suf
|
|||||||
, _block(cursor.block())
|
, _block(cursor.block())
|
||||||
, _maxBlockCount(maxBlockCount)
|
, _maxBlockCount(maxBlockCount)
|
||||||
{
|
{
|
||||||
|
_tokenize.setQtMocRunEnabled(true);
|
||||||
_tokenize.setSkipComments(true);
|
_tokenize.setSkipComments(true);
|
||||||
_text = _block.text().left(cursor.position() - cursor.block().position());
|
_text = _block.text().left(cursor.position() - cursor.block().position());
|
||||||
|
|
||||||
@@ -52,13 +53,10 @@ BackwardsScanner::BackwardsScanner(const QTextCursor &cursor, const QString &suf
|
|||||||
int BackwardsScanner::state() const
|
int BackwardsScanner::state() const
|
||||||
{ return _tokenize.state(); }
|
{ return _tokenize.state(); }
|
||||||
|
|
||||||
const QList<SimpleToken> &BackwardsScanner::tokens() const
|
SimpleToken BackwardsScanner::LA(int index) const
|
||||||
{ return _tokens; }
|
|
||||||
|
|
||||||
const SimpleToken &BackwardsScanner::LA(int index) const
|
|
||||||
{ return const_cast<BackwardsScanner *>(this)->fetchToken(_startToken - index); }
|
{ return const_cast<BackwardsScanner *>(this)->fetchToken(_startToken - index); }
|
||||||
|
|
||||||
const SimpleToken &BackwardsScanner::operator[](int index) const
|
SimpleToken BackwardsScanner::operator[](int index) const
|
||||||
{ return const_cast<BackwardsScanner *>(this)->fetchToken(index); }
|
{ return const_cast<BackwardsScanner *>(this)->fetchToken(index); }
|
||||||
|
|
||||||
const SimpleToken &BackwardsScanner::fetchToken(int i)
|
const SimpleToken &BackwardsScanner::fetchToken(int i)
|
||||||
@@ -72,16 +70,27 @@ const SimpleToken &BackwardsScanner::fetchToken(int i)
|
|||||||
} else {
|
} else {
|
||||||
++_blocksTokenized;
|
++_blocksTokenized;
|
||||||
|
|
||||||
QString blockText = _block.text();
|
const QString blockText = _block.text();
|
||||||
_text.prepend(blockText);
|
_text.prepend(blockText);
|
||||||
|
|
||||||
QList<SimpleToken> adaptedTokens;
|
QList<SimpleToken> adaptedTokens;
|
||||||
for (int i = 0; i < _tokens.size(); ++i) {
|
for (int i = 0; i < _tokens.size(); ++i) {
|
||||||
const SimpleToken &t = _tokens.at(i);
|
SimpleToken t = _tokens.at(i);
|
||||||
const int position = t.position() + blockText.length();
|
if (i == 0) {
|
||||||
adaptedTokens.append(SimpleToken(t.kind(),
|
Q_ASSERT(t.followsNewline());
|
||||||
position,
|
}
|
||||||
t.length(),
|
t.setPosition(t.position() + blockText.length());
|
||||||
_text.midRef(position, t.length())));
|
t.setText(_text.midRef(t.position(), t.length()));
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
Q_ASSERT(t.followsNewline());
|
||||||
|
}
|
||||||
|
|
||||||
|
adaptedTokens.append(t);
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
Q_ASSERT(adaptedTokens.last().followsNewline());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_tokens = _tokenize(blockText, previousBlockState(_block));
|
_tokens = _tokenize(blockText, previousBlockState(_block));
|
||||||
@@ -156,6 +165,17 @@ int BackwardsScanner::startOfMatchingBrace(int index) const
|
|||||||
--count;
|
--count;
|
||||||
--i;
|
--i;
|
||||||
} while (count != 0 && tk[i].isNot(T_EOF_SYMBOL));
|
} while (count != 0 && tk[i].isNot(T_EOF_SYMBOL));
|
||||||
|
} else if (tk[index - 1].is(T_RBRACE)) {
|
||||||
|
int i = index - 1;
|
||||||
|
int count = 0;
|
||||||
|
do {
|
||||||
|
if (tk[i].is(T_LBRACE)) {
|
||||||
|
if (! ++count)
|
||||||
|
return i;
|
||||||
|
} else if (tk[i].is(T_RBRACE))
|
||||||
|
--count;
|
||||||
|
--i;
|
||||||
|
} while (count != 0 && tk[i].isNot(T_EOF_SYMBOL));
|
||||||
} else if (tk[index - 1].is(T_GREATER)) {
|
} else if (tk[index - 1].is(T_GREATER)) {
|
||||||
int i = index - 1;
|
int i = index - 1;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@@ -167,7 +187,71 @@ int BackwardsScanner::startOfMatchingBrace(int index) const
|
|||||||
--count;
|
--count;
|
||||||
--i;
|
--i;
|
||||||
} while (count != 0 && tk[i].isNot(T_EOF_SYMBOL));
|
} while (count != 0 && tk[i].isNot(T_EOF_SYMBOL));
|
||||||
|
} else {
|
||||||
|
Q_ASSERT(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int BackwardsScanner::startOfLine(int index) const
|
||||||
|
{
|
||||||
|
const BackwardsScanner tk(*this);
|
||||||
|
|
||||||
|
forever {
|
||||||
|
const SimpleToken &tok = tk[index - 1];
|
||||||
|
|
||||||
|
if (tok.is(T_EOF_SYMBOL))
|
||||||
|
break;
|
||||||
|
else if (tok.followsNewline())
|
||||||
|
return index - 1;
|
||||||
|
|
||||||
|
--index;
|
||||||
|
}
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BackwardsScanner::startOfBlock(int index) const
|
||||||
|
{
|
||||||
|
const BackwardsScanner tk(*this);
|
||||||
|
|
||||||
|
const int start = index;
|
||||||
|
|
||||||
|
forever {
|
||||||
|
SimpleToken token = tk[index - 1];
|
||||||
|
|
||||||
|
if (token.is(T_EOF_SYMBOL)) {
|
||||||
|
break;
|
||||||
|
|
||||||
|
} else if (token.is(T_GREATER)) {
|
||||||
|
const int matchingBrace = startOfMatchingBrace(index);
|
||||||
|
|
||||||
|
if (matchingBrace != index && tk[matchingBrace - 1].is(T_TEMPLATE))
|
||||||
|
index = matchingBrace;
|
||||||
|
|
||||||
|
} else if (token.is(T_RPAREN) || token.is(T_RBRACKET) || token.is(T_RBRACE)) {
|
||||||
|
const int matchingBrace = startOfMatchingBrace(index);
|
||||||
|
|
||||||
|
if (matchingBrace != index)
|
||||||
|
index = matchingBrace;
|
||||||
|
|
||||||
|
} else if (token.is(T_LPAREN) || token.is(T_LBRACKET)) {
|
||||||
|
break; // unmatched brace
|
||||||
|
|
||||||
|
} else if (token.is(T_LBRACE)) {
|
||||||
|
return index - 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
--index;
|
||||||
|
}
|
||||||
|
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BackwardsScanner::indentation(int index) const
|
||||||
|
{
|
||||||
|
SimpleToken newline = operator[](startOfLine(index + 1));
|
||||||
|
return newline.position();
|
||||||
|
}
|
||||||
|
|||||||
@@ -55,17 +55,21 @@ public:
|
|||||||
QStringRef textRef(int begin, int end) const;
|
QStringRef textRef(int begin, int end) const;
|
||||||
|
|
||||||
// 1-based
|
// 1-based
|
||||||
const SimpleToken &LA(int index) const;
|
SimpleToken LA(int index) const;
|
||||||
|
|
||||||
// n-la token is [startToken - n]
|
// n-la token is [startToken - n]
|
||||||
const SimpleToken &operator[](int index) const; // ### deprecate
|
SimpleToken operator[](int index) const; // ### deprecate
|
||||||
|
|
||||||
|
int indentation(int index) const;
|
||||||
|
|
||||||
|
int startOfLine(int index) const;
|
||||||
int startOfMatchingBrace(int index) const;
|
int startOfMatchingBrace(int index) const;
|
||||||
|
int startOfBlock(int index) const;
|
||||||
|
|
||||||
int previousBlockState(const QTextBlock &block) const;
|
int previousBlockState(const QTextBlock &block) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const SimpleToken &fetchToken(int i);
|
const SimpleToken &fetchToken(int i);
|
||||||
const QList<SimpleToken> &tokens() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QList<SimpleToken> _tokens;
|
QList<SimpleToken> _tokens;
|
||||||
|
|||||||
@@ -35,6 +35,17 @@
|
|||||||
|
|
||||||
using namespace CPlusPlus;
|
using namespace CPlusPlus;
|
||||||
|
|
||||||
|
SimpleToken::SimpleToken(const Token &token, const QStringRef &text)
|
||||||
|
: _kind(token.f.kind)
|
||||||
|
, _flags(0)
|
||||||
|
, _position(token.begin())
|
||||||
|
, _length(token.f.length)
|
||||||
|
, _text(text)
|
||||||
|
{
|
||||||
|
f._whitespace = token.f.whitespace;
|
||||||
|
f._newline = token.f.newline;
|
||||||
|
}
|
||||||
|
|
||||||
bool SimpleToken::isLiteral() const
|
bool SimpleToken::isLiteral() const
|
||||||
{
|
{
|
||||||
return _kind >= T_FIRST_LITERAL && _kind <= T_LAST_LITERAL;
|
return _kind >= T_FIRST_LITERAL && _kind <= T_LAST_LITERAL;
|
||||||
@@ -60,6 +71,11 @@ bool SimpleToken::isObjCAtKeyword() const
|
|||||||
return _kind >= T_FIRST_OBJC_AT_KEYWORD && _kind <= T_LAST_OBJC_AT_KEYWORD;
|
return _kind >= T_FIRST_OBJC_AT_KEYWORD && _kind <= T_LAST_OBJC_AT_KEYWORD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *SimpleToken::name() const
|
||||||
|
{
|
||||||
|
return Token::name(_kind);
|
||||||
|
}
|
||||||
|
|
||||||
SimpleLexer::SimpleLexer()
|
SimpleLexer::SimpleLexer()
|
||||||
: _lastState(0),
|
: _lastState(0),
|
||||||
_skipComments(false),
|
_skipComments(false),
|
||||||
@@ -113,6 +129,7 @@ QList<SimpleToken> SimpleLexer::operator()(const QString &text, int state)
|
|||||||
Lexer lex(firstChar, lastChar);
|
Lexer lex(firstChar, lastChar);
|
||||||
lex.setQtMocRunEnabled(_qtMocRunEnabled);
|
lex.setQtMocRunEnabled(_qtMocRunEnabled);
|
||||||
lex.setObjCEnabled(_objCEnabled);
|
lex.setObjCEnabled(_objCEnabled);
|
||||||
|
lex.setStartWithNewline(true);
|
||||||
|
|
||||||
if (! _skipComments)
|
if (! _skipComments)
|
||||||
lex.setScanCommentTokens(true);
|
lex.setScanCommentTokens(true);
|
||||||
@@ -122,17 +139,26 @@ QList<SimpleToken> SimpleLexer::operator()(const QString &text, int state)
|
|||||||
|
|
||||||
bool inPreproc = false;
|
bool inPreproc = false;
|
||||||
|
|
||||||
|
bool first = true;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
Token tk;
|
Token tk;
|
||||||
lex(&tk);
|
lex(&tk);
|
||||||
if (tk.is(T_EOF_SYMBOL))
|
if (tk.is(T_EOF_SYMBOL))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
SimpleToken simpleTk;
|
Q_ASSERT(lex.tokenOffset() == tk.begin());
|
||||||
simpleTk._kind = int(tk.f.kind);
|
Q_ASSERT(lex.tokenLength() == tk.f.length);
|
||||||
simpleTk._position = int(lex.tokenOffset());
|
|
||||||
simpleTk._length = int(lex.tokenLength());
|
QStringRef spell = text.midRef(lex.tokenOffset(), lex.tokenLength());
|
||||||
simpleTk._text = text.midRef(simpleTk._position, simpleTk._length);
|
SimpleToken simpleTk(tk, spell);
|
||||||
|
|
||||||
|
if (first) {
|
||||||
|
first = false;
|
||||||
|
|
||||||
|
Q_ASSERT(tk.f.newline);
|
||||||
|
Q_ASSERT(simpleTk.followsNewline());
|
||||||
|
}
|
||||||
|
|
||||||
lex.setScanAngleStringLiteralTokens(false);
|
lex.setScanAngleStringLiteralTokens(false);
|
||||||
|
|
||||||
|
|||||||
@@ -37,21 +37,18 @@
|
|||||||
namespace CPlusPlus {
|
namespace CPlusPlus {
|
||||||
|
|
||||||
class SimpleLexer;
|
class SimpleLexer;
|
||||||
|
class Token;
|
||||||
|
|
||||||
class CPLUSPLUS_EXPORT SimpleToken
|
class CPLUSPLUS_EXPORT SimpleToken
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SimpleToken(int kind, int position, int length, const QStringRef &text)
|
SimpleToken(const Token &token, const QStringRef &text);
|
||||||
: _kind(kind)
|
|
||||||
, _position(position)
|
|
||||||
, _length(length)
|
|
||||||
, _text(text)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
SimpleToken()
|
SimpleToken()
|
||||||
: _kind(0),
|
: _kind(0)
|
||||||
_position(0),
|
, _flags(0)
|
||||||
_length(0)
|
, _position(0)
|
||||||
|
, _length(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
inline int kind() const
|
inline int kind() const
|
||||||
@@ -72,6 +69,12 @@ public:
|
|||||||
inline QStringRef text() const
|
inline QStringRef text() const
|
||||||
{ return _text; }
|
{ return _text; }
|
||||||
|
|
||||||
|
inline bool followsNewline() const
|
||||||
|
{ return f._newline; }
|
||||||
|
|
||||||
|
inline bool followsWhitespace() const
|
||||||
|
{ return f._whitespace; }
|
||||||
|
|
||||||
inline bool is(int k) const { return _kind == k; }
|
inline bool is(int k) const { return _kind == k; }
|
||||||
inline bool isNot(int k) const { return _kind != k; }
|
inline bool isNot(int k) const { return _kind != k; }
|
||||||
|
|
||||||
@@ -81,8 +84,27 @@ public:
|
|||||||
bool isComment() const;
|
bool isComment() const;
|
||||||
bool isObjCAtKeyword() const;
|
bool isObjCAtKeyword() const;
|
||||||
|
|
||||||
|
const char *name() const;
|
||||||
|
|
||||||
|
// internal
|
||||||
|
inline void setPosition(int position)
|
||||||
|
{ _position = position; }
|
||||||
|
|
||||||
|
// internal
|
||||||
|
inline void setText(const QStringRef &text)
|
||||||
|
{ _text = text; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int _kind;
|
short _kind;
|
||||||
|
union {
|
||||||
|
short _flags;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
short _newline: 1;
|
||||||
|
short _whitespace: 1;
|
||||||
|
} f;
|
||||||
|
};
|
||||||
|
|
||||||
int _position;
|
int _position;
|
||||||
int _length;
|
int _length;
|
||||||
QStringRef _text;
|
QStringRef _text;
|
||||||
|
|||||||
@@ -53,6 +53,7 @@
|
|||||||
#include <cplusplus/TokenUnderCursor.h>
|
#include <cplusplus/TokenUnderCursor.h>
|
||||||
#include <cplusplus/TypeOfExpression.h>
|
#include <cplusplus/TypeOfExpression.h>
|
||||||
#include <cplusplus/MatchingText.h>
|
#include <cplusplus/MatchingText.h>
|
||||||
|
#include <cplusplus/BackwardsScanner.h>
|
||||||
#include <cpptools/cppmodelmanagerinterface.h>
|
#include <cpptools/cppmodelmanagerinterface.h>
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
@@ -1263,6 +1264,7 @@ bool CPPEditor::isElectricCharacter(const QChar &ch) const
|
|||||||
{
|
{
|
||||||
if (ch == QLatin1Char('{') ||
|
if (ch == QLatin1Char('{') ||
|
||||||
ch == QLatin1Char('}') ||
|
ch == QLatin1Char('}') ||
|
||||||
|
ch == QLatin1Char(':') ||
|
||||||
ch == QLatin1Char('#')) {
|
ch == QLatin1Char('#')) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1473,6 +1475,40 @@ void CPPEditor::indentBlock(QTextDocument *doc, QTextBlock block, QChar typedCha
|
|||||||
const TextEditor::TextBlockIterator begin(doc->begin());
|
const TextEditor::TextBlockIterator begin(doc->begin());
|
||||||
const TextEditor::TextBlockIterator end(block.next());
|
const TextEditor::TextBlockIterator end(block.next());
|
||||||
|
|
||||||
|
QTextCursor tc(block);
|
||||||
|
tc.movePosition(QTextCursor::EndOfBlock);
|
||||||
|
|
||||||
|
BackwardsScanner tk(tc, QString(), 400);
|
||||||
|
const int tokenCount = tk.startToken();
|
||||||
|
const int indentSize = tabSettings().m_indentSize;
|
||||||
|
|
||||||
|
if (tokenCount != 0) {
|
||||||
|
const SimpleToken firstToken = tk[0];
|
||||||
|
|
||||||
|
if (firstToken.is(T_COLON)) {
|
||||||
|
const int indent = tk.indentation(-1) + // indentation of the previous newline
|
||||||
|
indentSize;
|
||||||
|
tabSettings().indentLine(block, indent);
|
||||||
|
return;
|
||||||
|
} else if ((firstToken.is(T_PUBLIC) || firstToken.is(T_PROTECTED) || firstToken.is(T_PRIVATE) ||
|
||||||
|
firstToken.is(T_Q_SIGNALS) || firstToken.is(T_Q_SLOTS)) && tk[1].is(T_COLON)) {
|
||||||
|
const int startOfBlock = tk.startOfBlock(0);
|
||||||
|
if (startOfBlock != 0) {
|
||||||
|
const int indent = tk.indentation(startOfBlock);
|
||||||
|
tabSettings().indentLine(block, indent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (firstToken.is(T_CASE) || firstToken.is(T_DEFAULT)) {
|
||||||
|
const int startOfBlock = tk.startOfBlock(0);
|
||||||
|
if (startOfBlock != 0) {
|
||||||
|
const int indent = tk.indentation(startOfBlock);
|
||||||
|
tabSettings().indentLine(block, indent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
indentCPPBlock(tabSettings(), block, begin, end, typedChar);
|
indentCPPBlock(tabSettings(), block, begin, end, typedChar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user