- enhancement: Improve auto indent.

This commit is contained in:
Roy Qu 2023-02-07 19:05:39 +08:00
parent 79ed9573d6
commit dd5df6912c
11 changed files with 144 additions and 258 deletions

View File

@ -7,6 +7,7 @@ Red Panda C++ Version 2.11
- fix: Parser can't correctly differentiate function and var initialization.
- fix: Respect encoding "Project default" when search/find occurrencies/open project units.
- enhancement: Show progress dialog when search/find occurrencies in large projects.
- enhancement: Improve auto indent.
Red Panda C++ Version 2.10

View File

@ -61,6 +61,7 @@ Editor::Editor(QWidget *parent):
{
}
Editor::Editor(QWidget *parent, const QString& filename,
const QByteArray& encoding,
Project* pProject, bool isNew,

View File

@ -1293,36 +1293,6 @@ void QSynEdit::clearUndo()
mRedoList->clear();
}
int QSynEdit::findIndentsStartLine(int line, QVector<int> indents)
{
line--;
if (line<0 || line>=mDocument->count())
return -1;
while (line>=1) {
SyntaxState range = mDocument->getSyntaxState(line);
QVector<int> newIndents = range.indents.mid(range.firstIndentThisLine);
int i = 0;
int len = indents.length();
while (i<len && !newIndents.isEmpty()) {
int indent = indents[i];
int idx = newIndents.lastIndexOf(indent);
if (idx >=0) {
newIndents.remove(idx,newIndents.size());
} else {
break;
}
i++;
}
if (i>=len) {
return line+1;
} else {
indents = range.matchingIndents + indents.mid(i);
}
line--;
}
return -1;
}
BufferCoord QSynEdit::getPreviousLeftBrace(int x, int y)
{
QChar Test;
@ -1605,9 +1575,6 @@ int QSynEdit::findCommentStartLine(int searchStartLine)
commentStartLine++;
break;
}
if (!range.matchingIndents.isEmpty()
|| range.firstIndentThisLine<range.indents.length())
break;
commentStartLine--;
}
if (commentStartLine<1)
@ -1636,6 +1603,8 @@ int QSynEdit::calcIndentSpaces(int line, const QString& lineText, bool addIndent
if (startLine>=1) {
//calculate the indents of last statement;
indentSpaces = leftSpaces(startLineText);
if (mSyntaxer->language() != ProgrammingLanguage::CPP)
return indentSpaces;
SyntaxState rangePreceeding = mDocument->getSyntaxState(startLine-1);
mSyntaxer->setState(rangePreceeding);
if (addIndent) {
@ -1665,135 +1634,42 @@ int QSynEdit::calcIndentSpaces(int line, const QString& lineText, bool addIndent
firstToken = mSyntaxer->getToken();
attr = mSyntaxer->getTokenAttribute();
}
bool indentAdded = false;
int additionIndent = 0;
QVector<int> matchingIndents;
int l;
if (attr->tokenType() == TokenType::Operator
&& (firstToken == '}')) {
// current line starts with '}', we should consider it to calc indents
matchingIndents = rangeAfterFirstToken.matchingIndents;
indentAdded = true;
l = startLine;
} else if (attr->tokenType() == TokenType::Operator
&& (firstToken == '{')
&& (rangePreceeding.getLastIndent()==IndentForStatement)) {
// current line starts with '{' and last statement not finished, we should consider it to calc indents
matchingIndents = rangeAfterFirstToken.matchingIndents;
indentAdded = true;
l = startLine;
} else if (mSyntaxer->language() == ProgrammingLanguage::CPP
&& trimmedLineText.startsWith('#')
qDebug()<<line<<lineText;
qDebug()<<(int)rangeAfterFirstToken.lastUnindent.type<<rangeAfterFirstToken.lastUnindent.line;
if (trimmedLineText.startsWith('#')
&& attr == ((CppSyntaxer *)mSyntaxer.get())->preprocessorAttribute()) {
indentAdded = true;
indentSpaces=0;
l=0;
} else if (mSyntaxer->language() == ProgrammingLanguage::CPP
&& mSyntaxer->isLastLineCommentNotFinished(rangePreceeding.state)
} else if (mSyntaxer->isLastLineCommentNotFinished(rangePreceeding.state)
) {
// last line is a not finished comment,
if (trimmedLineText.startsWith("*")) {
// this line start with "* "
// it means this line is a docstring, should indents according to
// the line the comment beginning , and add 1 additional space
additionIndent = 1;
int commentStartLine = findCommentStartLine(startLine-1);
SyntaxState range;
indentSpaces = leftSpaces(mDocument->getLine(commentStartLine-1));
indentSpaces = leftSpaces(mDocument->getLine(commentStartLine-1))+1;
range = mDocument->getSyntaxState(commentStartLine-1);
matchingIndents = range.matchingIndents;
indentAdded = true;
l = commentStartLine;
} else {
//indents according to the beginning of the comment and 2 additional space
additionIndent = 0;
int commentStartLine = findCommentStartLine(startLine-1);
SyntaxState range;
indentSpaces = leftSpaces(mDocument->getLine(commentStartLine-1))+2;
range = mDocument->getSyntaxState(commentStartLine-1);
matchingIndents = range.matchingIndents;
indentAdded = true;
l = startLine;
}
} else if ( mSyntaxer->isLastLineCommentNotFinished(statePrePre)
&& rangePreceeding.matchingIndents.isEmpty()
&& rangePreceeding.firstIndentThisLine>=rangePreceeding.indents.length()
&& !mSyntaxer->isLastLineCommentNotFinished(rangePreceeding.state)) {
// the preceeding line is the end of comment
// we should use the indents of the start line of the comment
int commentStartLine = findCommentStartLine(startLine-2);
SyntaxState range;
indentSpaces = leftSpaces(mDocument->getLine(commentStartLine-1));
range = mDocument->getSyntaxState(commentStartLine-1);
matchingIndents = range.matchingIndents;
indentAdded = true;
l = commentStartLine;
} else if (rangeAfterFirstToken.lastUnindent.type!=IndentType::None
&& firstToken=="}") {
IndentInfo matchingIndents = rangeAfterFirstToken.lastUnindent;
indentSpaces = leftSpaces(mDocument->getLine(matchingIndents.line));
} else if (firstToken=="{") {
IndentInfo matchingIndents = rangeAfterFirstToken.getLastIndent();
indentSpaces = leftSpaces(mDocument->getLine(matchingIndents.line));
} else if (rangePreceeding.getLastIndentType()!=IndentType::None) {
IndentInfo matchingIndents = rangePreceeding.getLastIndent();
indentSpaces = leftSpaces(mDocument->getLine(matchingIndents.line))+tabWidth();
} else {
// we just use infos till preceeding line's end to calc indents
matchingIndents = rangePreceeding.matchingIndents;
l = startLine-1;
indentSpaces = 0;
}
if (!matchingIndents.isEmpty()
) {
// find the indent's start line, and use it's indent as the default indent;
while (l>=1) {
SyntaxState range = mDocument->getSyntaxState(l-1);
QVector<int> newIndents = range.indents.mid(range.firstIndentThisLine);
int i = 0;
int len = matchingIndents.length();
while (i<len && !newIndents.isEmpty()) {
int indent = matchingIndents[i];
int idx = newIndents.lastIndexOf(indent);
if (idx >=0) {
newIndents.remove(idx,newIndents.length()-idx);
} else {
break;
}
i++;
}
if (i>=len) {
// we found the where the indent started
if (len>0 && !range.matchingIndents.isEmpty()
&&
( matchingIndents.back()== IndentForBrace
|| matchingIndents.back() == IndentForStatement
) ) {
// but it's not a complete statement
matchingIndents = range.matchingIndents;
} else {
indentSpaces = leftSpaces(mDocument->getLine(l-1));
if (newIndents.length()>0)
indentSpaces+=tabWidth();
break;
}
} else {
matchingIndents = range.matchingIndents + matchingIndents.mid(i);
}
l--;
}
}
if (!indentAdded) {
if (rangePreceeding.firstIndentThisLine < rangePreceeding.indents.length()) {
indentSpaces += tabWidth();
indentAdded = true;
}
}
if (!indentAdded && !startLineText.isEmpty()) {
BufferCoord coord;
QString token;
PTokenAttribute attr;
coord.line = startLine;
coord.ch = document()->getLine(startLine-1).length();
if (getTokenAttriAtRowCol(coord,token,attr)
&& attr->tokenType() == QSynedit::TokenType::Operator
&& token == ":") {
indentSpaces += tabWidth();
indentAdded = true;
}
}
indentSpaces += additionIndent;
}
}
return std::max(0,indentSpaces);

View File

@ -571,7 +571,6 @@ private:
void processGutterClick(QMouseEvent* event);
void clearUndo();
int findIndentsStartLine(int line, QVector<int> indents);
BufferCoord getPreviousLeftBrace(int x,int y);
bool canDoBlockIndent();

View File

@ -386,7 +386,7 @@ void CppSyntaxer::braceCloseProc()
} else {
mRange.blockEnded++ ;
}
popIndents(IndentForBrace);
popIndents(IndentType::Block);
}
void CppSyntaxer::braceOpenProc()
@ -400,20 +400,17 @@ void CppSyntaxer::braceOpenProc()
mRange.braceLevel += 1;
mRange.blockLevel += 1;
mRange.blockStarted++;
if (mRange.getLastIndent() == IndentForStatement) {
if (mRange.getLastIndentType() == IndentType::Statement) {
// if last indent is started by 'if' 'for' etc
// just replace it
while (mRange.getLastIndent() == IndentForStatement)
popIndents(IndentForStatement);
pushIndents(IndentForBrace);
// int idx = mRange.indents.length()-1;
// if (idx < mRange.firstIndentThisLine) {
// mRange.firstIndentThisLine = idx;
// }
// mRange.indents.replace(idx,1,BraceIndentType);
} else {
pushIndents(IndentForBrace);
}
int lastLine=-1;
while (mRange.getLastIndentType() == IndentType::Statement) {
popIndents(IndentType::Statement);
lastLine = mRange.lastUnindent.line;
}
pushIndents(IndentType::Block, lastLine);
} else
pushIndents(IndentType::Block);
}
void CppSyntaxer::colonProc()
@ -575,7 +572,7 @@ void CppSyntaxer::identProc()
if (isKeyword(word)) {
mTokenId = TokenId::Key;
if (CppStatementKeyWords.contains(word)) {
pushIndents(IndentForStatement);
pushIndents(IndentType::Statement);
}
} else {
mTokenId = TokenId::Identifier;
@ -908,7 +905,7 @@ void CppSyntaxer::roundCloseProc()
mRange.parenthesisLevel--;
if (mRange.parenthesisLevel<0)
mRange.parenthesisLevel=0;
popIndents(IndentForParenthesis);
popIndents(IndentType::Parenthesis);
}
void CppSyntaxer::roundOpenProc()
@ -916,7 +913,7 @@ void CppSyntaxer::roundOpenProc()
mRun += 1;
mTokenId = TokenId::Symbol;
mRange.parenthesisLevel++;
pushIndents(IndentForParenthesis);
pushIndents(IndentType::Parenthesis);
}
void CppSyntaxer::semiColonProc()
@ -925,8 +922,8 @@ void CppSyntaxer::semiColonProc()
mTokenId = TokenId::Symbol;
if (mRange.state == RangeState::rsAsm)
mRange.state = RangeState::rsUnknown;
while (mRange.getLastIndent() == IndentForStatement) {
popIndents(IndentForStatement);
while (mRange.getLastIndentType() == IndentType::Statement) {
popIndents(IndentType::Statement);
}
}
@ -997,7 +994,7 @@ void CppSyntaxer::squareCloseProc()
mRange.bracketLevel--;
if (mRange.bracketLevel<0)
mRange.bracketLevel=0;
popIndents(IndentForBracket);
popIndents(IndentType::Bracket);
}
void CppSyntaxer::squareOpenProc()
@ -1005,7 +1002,7 @@ void CppSyntaxer::squareOpenProc()
mRun+=1;
mTokenId = TokenId::Symbol;
mRange.bracketLevel++;
pushIndents(IndentForBracket);
pushIndents(IndentType::Bracket);
}
void CppSyntaxer::starProc()
@ -1365,26 +1362,28 @@ void CppSyntaxer::processChar()
}
}
void CppSyntaxer::popIndents(int indentType)
void CppSyntaxer::popIndents(IndentType indentType)
{
while (!mRange.indents.isEmpty() && mRange.indents.back()!=indentType) {
// qDebug()<<"----";
// for (IndentInfo info:mRange.indents)
// qDebug()<<(int)info.type<<info.line;
// qDebug()<<"****";
while (!mRange.indents.isEmpty() && mRange.indents.back().type!=indentType) {
mRange.indents.pop_back();
}
if (!mRange.indents.isEmpty()) {
int idx = mRange.indents.length()-1;
if (idx < mRange.firstIndentThisLine) {
mRange.matchingIndents.append(mRange.indents[idx]);
}
mRange.lastUnindent=mRange.indents.back();
mRange.indents.pop_back();
} else {
mRange.lastUnindent=IndentInfo{indentType,0};
}
}
void CppSyntaxer::pushIndents(int indentType)
void CppSyntaxer::pushIndents(IndentType indentType, int line)
{
int idx = mRange.indents.length();
if (idx<mRange.firstIndentThisLine)
mRange.firstIndentThisLine = idx;
mRange.indents.push_back(indentType);
if (line==-1)
line = mLineNumber;
mRange.indents.push_back(IndentInfo{indentType,line});
}
const QSet<QString> &CppSyntaxer::customTypeKeywords() const
@ -1572,11 +1571,6 @@ void CppSyntaxer::setLine(const QString &newLine, int lineNumber)
mLineSize = mLine.size();
mLineNumber = lineNumber;
mRun = 0;
mRange.blockStarted = 0;
mRange.blockEnded = 0;
mRange.blockEndedLastLine = 0;
mRange.firstIndentThisLine = mRange.indents.length();
mRange.matchingIndents.clear();
next();
}
@ -1592,9 +1586,8 @@ void CppSyntaxer::setState(const SyntaxState& rangeState)
mRange.blockStarted = 0;
mRange.blockEnded = 0;
mRange.blockEndedLastLine = 0;
mRange.firstIndentThisLine = mRange.indents.length();
mRange.lastUnindent=IndentInfo{IndentType::None,0};
mRange.hasTrailingSpaces = false;
mRange.matchingIndents.clear();
}
void CppSyntaxer::resetState()
@ -1608,8 +1601,7 @@ void CppSyntaxer::resetState()
mRange.blockEnded = 0;
mRange.blockEndedLastLine = 0;
mRange.indents.clear();
mRange.firstIndentThisLine = 0;
mRange.matchingIndents.clear();
mRange.lastUnindent=IndentInfo{IndentType::None,0};
mRange.hasTrailingSpaces = false;
mAsmStart = false;
}

View File

@ -134,8 +134,8 @@ private:
void unknownProc();
void xorSymbolProc();
void processChar();
void popIndents(int indentType);
void pushIndents(int indentType);
void popIndents(IndentType indentType);
void pushIndents(IndentType indentType, int line=-1);
private:
bool mAsmStart;

View File

@ -13,8 +13,8 @@ void CustomHighlighterV1::resetState()
mRange.bracketLevel = 0;
mRange.parenthesisLevel = 0;
mRange.indents.clear();
mRange.firstIndentThisLine = 0;
mRange.matchingIndents.clear();
mRange.lastUnindent=IndentInfo{IndentType::None,0};
mRange.hasTrailingSpaces=false;
}
QString CustomHighlighterV1::languageName()

View File

@ -308,7 +308,7 @@ void GLSLSyntaxer::braceCloseProc()
} else {
mRange.blockEnded++ ;
}
popIndents(IndentForBrace);
popIndents(IndentType::Block);
}
void GLSLSyntaxer::braceOpenProc()
@ -318,20 +318,17 @@ void GLSLSyntaxer::braceOpenProc()
mRange.braceLevel += 1;
mRange.blockLevel += 1;
mRange.blockStarted += 1;
if (mRange.getLastIndent() == IndentForStatement) {
if (mRange.getLastIndentType() == IndentType::Statement) {
// if last indent is started by 'if' 'for' etc
// just replace it
while (mRange.getLastIndent() == IndentForStatement)
popIndents(IndentForStatement);
pushIndents(IndentForBrace);
// int idx = mRange.indents.length()-1;
// if (idx < mRange.firstIndentThisLine) {
// mRange.firstIndentThisLine = idx;
// }
// mRange.indents.replace(idx,1,BraceIndentType);
} else {
pushIndents(IndentForBrace);
}
int lastLine=-1;
while (mRange.getLastIndentType() == IndentType::Statement) {
popIndents(IndentType::Statement);
lastLine = mRange.lastUnindent.line;
}
pushIndents(IndentType::Block, lastLine);
} else
pushIndents(IndentType::Block);
}
void GLSLSyntaxer::colonProc()
@ -465,7 +462,7 @@ void GLSLSyntaxer::identProc()
if (isKeyword(word)) {
mTokenId = TokenId::Key;
if (GLSLStatementKeyWords.contains(word)) {
pushIndents(IndentForStatement);
pushIndents(IndentType::Statement);
}
} else {
mTokenId = TokenId::Identifier;
@ -803,7 +800,7 @@ void GLSLSyntaxer::roundCloseProc()
mRange.parenthesisLevel--;
if (mRange.parenthesisLevel<0)
mRange.parenthesisLevel=0;
popIndents(IndentForParenthesis);
popIndents(IndentType::Parenthesis);
}
void GLSLSyntaxer::roundOpenProc()
@ -811,15 +808,15 @@ void GLSLSyntaxer::roundOpenProc()
mRun += 1;
mTokenId = TokenId::Symbol;
mRange.parenthesisLevel++;
pushIndents(IndentForParenthesis);
pushIndents(IndentType::Parenthesis);
}
void GLSLSyntaxer::semiColonProc()
{
mRun += 1;
mTokenId = TokenId::Symbol;
while (mRange.getLastIndent() == IndentForStatement) {
popIndents(IndentForStatement);
while (mRange.getLastIndentType() == IndentType::Statement) {
popIndents(IndentType::Statement);
}
}
@ -870,7 +867,7 @@ void GLSLSyntaxer::squareCloseProc()
mRange.bracketLevel--;
if (mRange.bracketLevel<0)
mRange.bracketLevel=0;
popIndents(IndentForBracket);
popIndents(IndentType::Bracket);
}
void GLSLSyntaxer::squareOpenProc()
@ -878,7 +875,7 @@ void GLSLSyntaxer::squareOpenProc()
mRun+=1;
mTokenId = TokenId::Symbol;
mRange.bracketLevel++;
pushIndents(IndentForBracket);
pushIndents(IndentType::Bracket);
}
void GLSLSyntaxer::starProc()
@ -1227,26 +1224,24 @@ void GLSLSyntaxer::processChar()
}
}
void GLSLSyntaxer::popIndents(int indentType)
void GLSLSyntaxer::popIndents(IndentType indentType)
{
while (!mRange.indents.isEmpty() && mRange.indents.back()!=indentType) {
while (!mRange.indents.isEmpty() && mRange.indents.back().type!=indentType) {
mRange.indents.pop_back();
}
if (!mRange.indents.isEmpty()) {
int idx = mRange.indents.length()-1;
if (idx < mRange.firstIndentThisLine) {
mRange.matchingIndents.append(mRange.indents[idx]);
}
mRange.lastUnindent=mRange.indents.back();
mRange.indents.pop_back();
} else {
mRange.lastUnindent=IndentInfo{indentType,0};
}
}
void GLSLSyntaxer::pushIndents(int indentType)
void GLSLSyntaxer::pushIndents(IndentType indentType, int line)
{
int idx = mRange.indents.length();
if (idx<mRange.firstIndentThisLine)
mRange.firstIndentThisLine = idx;
mRange.indents.push_back(indentType);
if (line==-1)
line = mLineNumber;
mRange.indents.push_back(IndentInfo{indentType,line});
}
bool GLSLSyntaxer::getTokenFinished() const
@ -1388,12 +1383,6 @@ void GLSLSyntaxer::setLine(const QString &newLine, int lineNumber)
mLine = mLineString.data();
mLineNumber = lineNumber;
mRun = 0;
mRange.blockLevel = 0;
mRange.blockStarted = 0;
mRange.blockEnded = 0;
mRange.blockEndedLastLine = 0;
mRange.firstIndentThisLine = mRange.indents.length();
mRange.matchingIndents.clear();
next();
}
@ -1406,12 +1395,7 @@ void GLSLSyntaxer::setState(const SyntaxState& rangeState)
{
mRange = rangeState;
// current line's left / right parenthesis count should be reset before parsing each line
mRange.blockLevel = 0;
mRange.blockStarted = 0;
mRange.blockEnded = 0;
mRange.blockEndedLastLine = 0;
mRange.firstIndentThisLine = mRange.indents.length();
mRange.matchingIndents.clear();
mRange.lastUnindent=IndentInfo{IndentType::None,0};
mRange.hasTrailingSpaces = false;
}
@ -1426,8 +1410,7 @@ void GLSLSyntaxer::resetState()
mRange.blockEnded = 0;
mRange.blockEndedLastLine = 0;
mRange.indents.clear();
mRange.firstIndentThisLine = 0;
mRange.matchingIndents.clear();
mRange.lastUnindent=IndentInfo{IndentType::None,0};
mRange.hasTrailingSpaces = false;
}

View File

@ -130,8 +130,8 @@ private:
void unknownProc();
void xorSymbolProc();
void processChar();
void popIndents(int indentType);
void pushIndents(int indentType);
void popIndents(IndentType indentType);
void pushIndents(IndentType indentType, int line=-1);
private:
SyntaxState mRange;

View File

@ -252,30 +252,52 @@ bool SyntaxState::operator==(const SyntaxState &s2)
{
// indents contains the information of brace/parenthesis/brackets embedded levels
return (state == s2.state)
&& (blockLevel == s2.blockLevel) // needed by block folding
&& (blockStarted == s2.blockStarted) // needed by block folding
&& (blockEnded == s2.blockEnded) // needed by block folding;
&& (blockEndedLastLine == s2.blockEndedLastLine) //needed by block folding;
&& (braceLevel == s2.braceLevel) // current braces embedding level (needed by rainbow color)
&& (bracketLevel == s2.bracketLevel) // current brackets embedding level (needed by rainbow color)
&& (parenthesisLevel == s2.parenthesisLevel) // current parenthesis embedding level (needed by rainbow color)
&& (indents == s2.indents)
&& (lastUnindent == s2.lastUnindent)
;
}
int SyntaxState::getLastIndent()
IndentInfo SyntaxState::getLastIndent()
{
if (indents.isEmpty())
return -1;
return IndentInfo{IndentType::None,0};
return indents.back();
}
IndentType SyntaxState::getLastIndentType()
{
if (indents.isEmpty())
return IndentType::None;
return indents.back().type;
}
SyntaxState::SyntaxState():
state(0),
blockLevel(0),
blockStarted(0),
blockEnded(0),
blockEndedLastLine(0),
braceLevel(0),
bracketLevel(0),
parenthesisLevel(0),
state{0},
blockLevel{0},
blockStarted{0},
blockEnded{0},
blockEndedLastLine{0},
braceLevel{0},
bracketLevel{0},
parenthesisLevel{0},
// leftBraces(0),
// rightBraces(0),
firstIndentThisLine(0),
hasTrailingSpaces(false)
lastUnindent{IndentType::None,0},
hasTrailingSpaces{false}
{
}
bool IndentInfo::operator==(const IndentInfo &i2) const
{
return type==i2.type && line==i2.line;
}
}

View File

@ -27,11 +27,20 @@
#include "../types.h"
namespace QSynedit {
enum IndentType {
IndentForBrace,
IndentForParenthesis,
IndentForBracket,
IndentForStatement,
enum class IndentType {
Brace,
Parenthesis,
Bracket,
Statement,
Block,
None
};
struct IndentInfo {
IndentType type;
int line;
bool operator==(const IndentInfo &i2) const;
};
struct SyntaxState {
@ -45,15 +54,18 @@ struct SyntaxState {
int parenthesisLevel; // current parenthesis embedding level (needed by rainbow color)
// int leftBraces; // unpairing left braces in the current line ( needed by block folding)
// int rightBraces; // unparing right braces in the current line (needed by block folding)
QVector<int> indents; // indents stack (needed by auto indent)
int firstIndentThisLine; /* index of first indent that appended to the indents
* stack at this line ( need by auto indent) */
QVector<int> matchingIndents; /* the indent matched ( and removed )
but not started at this line
(need by auto indent) */
QVector<IndentInfo> indents;
IndentInfo lastUnindent;
// QVector<int> indents; // indents stack (needed by auto indent)
// int firstIndentThisLine; /* index of first indent that appended to the indents
// * stack at this line ( need by auto indent) */
// QVector<int> matchingIndents; /* the indent matched ( and removed )
// but not started at this line
// (need by auto indent) */
bool hasTrailingSpaces;
bool operator==(const SyntaxState& s2);
int getLastIndent();
IndentInfo getLastIndent();
IndentType getLastIndentType();
SyntaxState();
};