From e5c7d0f10acdd98e29d89ef9bb778f6f2000c1d9 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen <erik.verbruggen@nokia.com> Date: Mon, 16 Nov 2009 12:38:47 +0100 Subject: [PATCH] Fixed the QML indenting. Done with Roberto Raggi. --- src/plugins/qmleditor/qmleditor.cpp | 81 +++++++++++++------ src/plugins/qmleditor/qmleditor.h | 2 + .../qscripthighlighter/qscripthighlighter.cpp | 2 +- .../qscriptincrementalscanner.cpp | 6 +- .../qscriptincrementalscanner.h | 4 +- 5 files changed, 67 insertions(+), 28 deletions(-) diff --git a/src/plugins/qmleditor/qmleditor.cpp b/src/plugins/qmleditor/qmleditor.cpp index 2819b87f68f..539726b3661 100644 --- a/src/plugins/qmleditor/qmleditor.cpp +++ b/src/plugins/qmleditor/qmleditor.cpp @@ -70,6 +70,7 @@ enum { using namespace QmlJS; using namespace QmlJS::AST; +using namespace SharedTools; namespace QmlEditor { namespace Internal { @@ -634,49 +635,81 @@ bool ScriptEditor::isElectricCharacter(const QChar &ch) const return false; } -void ScriptEditor::indentBlock(QTextDocument *, QTextBlock block, QChar typedChar) +bool ScriptEditor::isClosingBrace(const QList<QScriptIncrementalScanner::Token> &tokens) const { - TextEditor::TabSettings ts = tabSettings(); - if (typedChar == QLatin1Char('}') || typedChar == QLatin1Char(']') - || (typedChar == QChar::Null - && (block.text().trimmed() == "}" || block.text().trimmed() == "]"))) { + if (tokens.size() == 1) { + const QScriptIncrementalScanner::Token firstToken = tokens.first(); - QTextCursor tc(block); + return firstToken.is(QScriptIncrementalScanner::Token::RightBrace) || firstToken.is(QScriptIncrementalScanner::Token::RightBracket); + } - if (typedChar == QLatin1Char('}') || typedChar == QLatin1Char(']')) - tc = textCursor(); + return false; +} - if (TextEditor::TextBlockUserData::findPreviousBlockOpenParenthesis(&tc)) { - const QString text = tc.block().text(); - int indent = ts.columnAt(text, ts.firstNonSpace(text)); - ts.indentLine(block, indent); - return; - } - } +static int blockBraceDepth(const QTextBlock &block) +{ + int state = block.userState(); + if (state == -1) + return 0; + + return (state >> 8) & 0xFF; +} - int indent = 0; - int extraIndent = 0; +static int blockStartState(const QTextBlock &block) +{ + int state = block.userState(); - if (block.previous().isValid()) { - const int braceDepth = qMax(0, block.previous().userState() >> 8); - const int previousBraceDepth = qMax(0, block.previous().previous().userState() >> 8); + if (state == -1) + return 0; + else + return state & 0xff; +} - if (braceDepth > previousBraceDepth) - extraIndent = ts.m_indentSize * (braceDepth - previousBraceDepth); +void ScriptEditor::indentBlock(QTextDocument *, QTextBlock block, QChar typedChar) +{ + TextEditor::TabSettings ts = tabSettings(); + + QTextCursor tc(block); + + const QString blockText = block.text(); + int startState = blockStartState(block.previous()); + + QScriptIncrementalScanner scanner; + const QList<QScriptIncrementalScanner::Token> tokens = scanner(blockText, startState); + + if (! tokens.isEmpty()) { + const QScriptIncrementalScanner::Token tk = tokens.first(); + + if (tk.is(QScriptIncrementalScanner::Token::RightBrace) + || tk.is(QScriptIncrementalScanner::Token::RightBracket)) { + if (TextEditor::TextBlockUserData::findPreviousBlockOpenParenthesis(&tc)) { + const QString text = tc.block().text(); + int indent = ts.columnAt(text, ts.firstNonSpace(text)); + ts.indentLine(block, indent); + return; + } + } } + int initialIndent = 0; QTextBlock it = block.previous(); for (; it.isValid(); it = it.previous()) { const QString text = it.text(); if (! text.isEmpty()) { - indent = ts.columnAt(text, ts.firstNonSpace(text)); + initialIndent = ts.columnAt(text, ts.firstNonSpace(text)); break; } } - ts.indentLine(block, extraIndent + indent); + // default indent is initialIndent .. + + const int braceDepth = blockBraceDepth(block.previous()); + const int previousBraceDepth = blockBraceDepth(block.previous().previous()); + const int delta = qMax(0, braceDepth - previousBraceDepth); + int indent = initialIndent + (delta * ts.m_indentSize); + ts.indentLine(block, indent); } TextEditor::BaseTextEditorEditable *ScriptEditor::createEditableInterface() diff --git a/src/plugins/qmleditor/qmleditor.h b/src/plugins/qmleditor/qmleditor.h index ac4692bc4de..7afd46008d2 100644 --- a/src/plugins/qmleditor/qmleditor.h +++ b/src/plugins/qmleditor/qmleditor.h @@ -35,6 +35,7 @@ #include "qmljsastfwd_p.h" #include "qmljsengine_p.h" #include "qmldocument.h" +#include "qscriptincrementalscanner.h" QT_BEGIN_NAMESPACE class QComboBox; @@ -134,6 +135,7 @@ protected: private: virtual bool isElectricCharacter(const QChar &ch) const; virtual void indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar); + bool isClosingBrace(const QList<SharedTools::QScriptIncrementalScanner::Token> &tokens) const; QString wordUnderCursor() const; diff --git a/src/shared/qscripthighlighter/qscripthighlighter.cpp b/src/shared/qscripthighlighter/qscripthighlighter.cpp index a028ac4d7ba..f871aeb45ff 100644 --- a/src/shared/qscripthighlighter/qscripthighlighter.cpp +++ b/src/shared/qscripthighlighter/qscripthighlighter.cpp @@ -58,7 +58,7 @@ bool QScriptHighlighter::isDuiEnabled() const void QScriptHighlighter::highlightBlock(const QString &text) { - m_scanner(onBlockStart(), text); + m_scanner(text, onBlockStart()); QTextCharFormat emptyFormat; int lastEnd = 0; diff --git a/src/shared/qscripthighlighter/qscriptincrementalscanner.cpp b/src/shared/qscripthighlighter/qscriptincrementalscanner.cpp index 851110f6004..9ea05fa2f22 100644 --- a/src/shared/qscripthighlighter/qscriptincrementalscanner.cpp +++ b/src/shared/qscripthighlighter/qscriptincrementalscanner.cpp @@ -19,7 +19,7 @@ void QScriptIncrementalScanner::reset() m_tokens.clear(); } -void QScriptIncrementalScanner::operator()(int startState, const QString &text) +QList<QScriptIncrementalScanner::Token> QScriptIncrementalScanner::operator()(const QString &text, int startState) { reset(); @@ -78,7 +78,7 @@ void QScriptIncrementalScanner::operator()(int startState, const QString &text) int state = startState; if (text.isEmpty()) { blockEnd(state, 0); - return; + return m_tokens; } int input = -1; @@ -268,6 +268,8 @@ void QScriptIncrementalScanner::operator()(int startState, const QString &text) } blockEnd(state, firstNonSpace); + + return m_tokens; } void QScriptIncrementalScanner::insertToken(int start, int length, Token::Kind kind, bool forceNewToken) diff --git a/src/shared/qscripthighlighter/qscriptincrementalscanner.h b/src/shared/qscripthighlighter/qscriptincrementalscanner.h index 531a37464ee..253417d5214 100644 --- a/src/shared/qscripthighlighter/qscriptincrementalscanner.h +++ b/src/shared/qscripthighlighter/qscriptincrementalscanner.h @@ -35,6 +35,8 @@ public: inline Token(int o, int l, Kind k): offset(o), length(l), kind(k) {} inline int end() const { return offset + length; } + inline bool is(int k) const { return k == kind; } + inline bool isNot(int k) const { return k != kind; } }; public: @@ -46,7 +48,7 @@ public: void reset(); - void operator()(int startState, const QString &text); + QList<QScriptIncrementalScanner::Token> operator()(const QString &text, int startState = 0); int endState() const { return m_endState; } -- GitLab