Commit 6c9670c3 authored by Roberto Raggi's avatar Roberto Raggi
Browse files

Use the backward scanner to indent labeled statements, ctor-initializers and access specifiers.

parent caa164a4
...@@ -38,6 +38,7 @@ BackwardsScanner::BackwardsScanner(const QTextCursor &cursor, const QString &suf ...@@ -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 ...@@ -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) ...@@ -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 ...@@ -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 ...@@ -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;
}
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; 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: ...@@ -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 @@ ...@@ -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 ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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: ...@@ -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: ...@@ -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 @@ ...@@ -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 ...@@ -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 ...@@ -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);
} }
......
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