forked from qt-creator/qt-creator
Rework code folding
The new and cleaner foldingIndent in the block user data will make it easier to support other kinds of indentation for various other programming languages (like Python).
This commit is contained in:
@@ -44,6 +44,7 @@ Highlighter::Highlighter(QTextDocument *parent)
|
||||
{
|
||||
m_currentBlockParentheses.reserve(20);
|
||||
m_braceDepth = 0;
|
||||
m_foldingIndent = 0;
|
||||
}
|
||||
|
||||
Highlighter::~Highlighter()
|
||||
@@ -102,27 +103,27 @@ void Highlighter::highlightBlock(const QString &text)
|
||||
break;
|
||||
|
||||
case Token::LeftParenthesis:
|
||||
onOpeningParenthesis('(', token.offset);
|
||||
onOpeningParenthesis('(', token.offset, index == 0);
|
||||
break;
|
||||
|
||||
case Token::RightParenthesis:
|
||||
onClosingParenthesis(')', token.offset);
|
||||
onClosingParenthesis(')', token.offset, index == tokens.size()-1);
|
||||
break;
|
||||
|
||||
case Token::LeftBrace:
|
||||
onOpeningParenthesis('{', token.offset);
|
||||
onOpeningParenthesis('{', token.offset, index == 0);
|
||||
break;
|
||||
|
||||
case Token::RightBrace:
|
||||
onClosingParenthesis('}', token.offset);
|
||||
onClosingParenthesis('}', token.offset, index == tokens.size()-1);
|
||||
break;
|
||||
|
||||
case Token::LeftBracket:
|
||||
onOpeningParenthesis('[', token.offset);
|
||||
onOpeningParenthesis('[', token.offset, index == 0);
|
||||
break;
|
||||
|
||||
case Token::RightBracket:
|
||||
onClosingParenthesis(']', token.offset);
|
||||
onClosingParenthesis(']', token.offset, index == tokens.size()-1);
|
||||
break;
|
||||
|
||||
case Token::Identifier: {
|
||||
@@ -232,12 +233,8 @@ void Highlighter::highlightBlock(const QString &text)
|
||||
|
||||
setFormat(previousTokenEnd, text.length() - previousTokenEnd, m_formats[VisualWhitespace]);
|
||||
|
||||
int firstNonSpace = 0;
|
||||
if (! tokens.isEmpty())
|
||||
firstNonSpace = tokens.first().offset;
|
||||
|
||||
setCurrentBlockState(m_scanner.state());
|
||||
onBlockEnd(m_scanner.state(), firstNonSpace);
|
||||
onBlockEnd(m_scanner.state());
|
||||
}
|
||||
|
||||
bool Highlighter::maybeQmlKeyword(const QStringRef &text) const
|
||||
@@ -301,6 +298,12 @@ int Highlighter::onBlockStart()
|
||||
{
|
||||
m_currentBlockParentheses.clear();
|
||||
m_braceDepth = 0;
|
||||
m_foldingIndent = 0;
|
||||
if (TextEditor::TextBlockUserData *userData = TextEditor::BaseTextDocumentLayout::testUserData(currentBlock())) {
|
||||
userData->setFoldingIndent(0);
|
||||
userData->setFoldingStartIncluded(false);
|
||||
userData->setFoldingEndIncluded(false);
|
||||
}
|
||||
|
||||
int state = 0;
|
||||
int previousState = previousBlockState();
|
||||
@@ -308,56 +311,41 @@ int Highlighter::onBlockStart()
|
||||
state = previousState & 0xff;
|
||||
m_braceDepth = previousState >> 8;
|
||||
}
|
||||
m_foldingIndent = m_braceDepth;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
void Highlighter::onBlockEnd(int state, int firstNonSpace)
|
||||
void Highlighter::onBlockEnd(int state)
|
||||
{
|
||||
typedef TextEditor::TextBlockUserData TextEditorBlockData;
|
||||
|
||||
setCurrentBlockState((m_braceDepth << 8) | state);
|
||||
|
||||
// Set block data parentheses. Force creation of block data unless empty
|
||||
TextEditorBlockData *blockData = 0;
|
||||
|
||||
if (QTextBlockUserData *userData = currentBlockUserData())
|
||||
blockData = static_cast<TextEditorBlockData *>(userData);
|
||||
|
||||
if (!blockData && !m_currentBlockParentheses.empty()) {
|
||||
blockData = new TextEditorBlockData;
|
||||
setCurrentBlockUserData(blockData);
|
||||
}
|
||||
if (blockData) {
|
||||
blockData->setParentheses(m_currentBlockParentheses);
|
||||
blockData->setClosingCollapseMode(TextEditor::TextBlockUserData::NoClosingCollapse);
|
||||
blockData->setCollapseMode(TextEditor::TextBlockUserData::NoCollapse);
|
||||
}
|
||||
if (!m_currentBlockParentheses.isEmpty()) {
|
||||
QTC_ASSERT(blockData, return);
|
||||
int collapse = Parenthesis::collapseAtPos(m_currentBlockParentheses);
|
||||
if (collapse >= 0) {
|
||||
if (collapse == firstNonSpace)
|
||||
blockData->setCollapseMode(TextEditor::TextBlockUserData::CollapseThis);
|
||||
else
|
||||
blockData->setCollapseMode(TextEditor::TextBlockUserData::CollapseAfter);
|
||||
}
|
||||
if (Parenthesis::hasClosingCollapse(m_currentBlockParentheses))
|
||||
blockData->setClosingCollapseMode(TextEditor::TextBlockUserData::NoClosingCollapse);
|
||||
}
|
||||
TextEditor::BaseTextDocumentLayout::setParentheses(currentBlock(), m_currentBlockParentheses);
|
||||
TextEditor::BaseTextDocumentLayout::setFoldingIndent(currentBlock(), m_foldingIndent);
|
||||
}
|
||||
|
||||
void Highlighter::onOpeningParenthesis(QChar parenthesis, int pos)
|
||||
void Highlighter::onOpeningParenthesis(QChar parenthesis, int pos, bool atStart)
|
||||
{
|
||||
if (parenthesis == QLatin1Char('{') || parenthesis == QLatin1Char('['))
|
||||
if (parenthesis == QLatin1Char('{') || parenthesis == QLatin1Char('[')) {
|
||||
++m_braceDepth;
|
||||
// if a folding block opens at the beginning of a line, treat the entire line
|
||||
// as if it were inside the folding block
|
||||
if (atStart)
|
||||
TextEditor::BaseTextDocumentLayout::userData(currentBlock())->setFoldingStartIncluded(true);
|
||||
}
|
||||
m_currentBlockParentheses.push_back(Parenthesis(Parenthesis::Opened, parenthesis, pos));
|
||||
}
|
||||
|
||||
void Highlighter::onClosingParenthesis(QChar parenthesis, int pos)
|
||||
void Highlighter::onClosingParenthesis(QChar parenthesis, int pos, bool atEnd)
|
||||
{
|
||||
if (parenthesis == QLatin1Char('}') || parenthesis == QLatin1Char(']'))
|
||||
if (parenthesis == QLatin1Char('}') || parenthesis == QLatin1Char(']')) {
|
||||
--m_braceDepth;
|
||||
if (atEnd)
|
||||
TextEditor::BaseTextDocumentLayout::userData(currentBlock())->setFoldingEndIncluded(true);
|
||||
else
|
||||
m_foldingIndent = qMin(m_braceDepth, m_foldingIndent); // folding indent is the minimum brace depth of a block
|
||||
}
|
||||
m_currentBlockParentheses.push_back(Parenthesis(Parenthesis::Closed, parenthesis, pos));
|
||||
}
|
||||
|
||||
|
||||
@@ -78,12 +78,12 @@ protected:
|
||||
virtual void highlightBlock(const QString &text);
|
||||
|
||||
int onBlockStart();
|
||||
void onBlockEnd(int state, int firstNonSpace);
|
||||
void onBlockEnd(int state);
|
||||
|
||||
// The functions are notified whenever parentheses are encountered.
|
||||
// Custom behaviour can be added, for example storing info for indenting.
|
||||
void onOpeningParenthesis(QChar parenthesis, int pos);
|
||||
void onClosingParenthesis(QChar parenthesis, int pos);
|
||||
void onOpeningParenthesis(QChar parenthesis, int pos, bool atStart);
|
||||
void onClosingParenthesis(QChar parenthesis, int pos, bool atEnd);
|
||||
|
||||
bool maybeQmlKeyword(const QStringRef &text) const;
|
||||
bool maybeQmlBuiltinType(const QStringRef &text) const;
|
||||
@@ -94,6 +94,7 @@ private:
|
||||
|
||||
bool m_qmlEnabled;
|
||||
int m_braceDepth;
|
||||
int m_foldingIndent;
|
||||
|
||||
QmlJS::Scanner m_scanner;
|
||||
Parentheses m_currentBlockParentheses;
|
||||
|
||||
Reference in New Issue
Block a user