diff options
-rw-r--r-- | src/qmldom/qqmldomindentinglinewriter.cpp | 171 | ||||
-rw-r--r-- | src/qmldom/qqmldomindentinglinewriter_p.h | 3 | ||||
-rw-r--r-- | src/qmldom/qqmldomlinewriter_p.h | 2 |
3 files changed, 92 insertions, 84 deletions
diff --git a/src/qmldom/qqmldomindentinglinewriter.cpp b/src/qmldom/qqmldomindentinglinewriter.cpp index 99f81c1717..65dcdfade8 100644 --- a/src/qmldom/qqmldomindentinglinewriter.cpp +++ b/src/qmldom/qqmldomindentinglinewriter.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qqmldomindentinglinewriter_p.h" +#include "qqmldomlinewriter_p.h" #include <QtCore/QCoreApplication> #include <QtCore/QRegularExpression> @@ -10,6 +11,9 @@ QT_BEGIN_NAMESPACE namespace QQmlJS { namespace Dom { +static QSet<int> splitSequence = { QQmlJSGrammar::T_COMMA, QQmlJSGrammar::T_AND_AND, + QQmlJSGrammar::T_OR_OR, QQmlJSGrammar::T_LPAREN }; + FormatPartialStatus &IndentingLineWriter::fStatus() { if (!m_fStatusValid) { @@ -26,99 +30,100 @@ void IndentingLineWriter::willCommit() void IndentingLineWriter::reindentAndSplit(const QString &eol, bool eof) { - bool shouldReindent = m_reindent; -indentAgain: // maybe re-indent - if (shouldReindent && m_columnNr == 0) { + if (m_reindent && m_columnNr == 0) setLineIndent(fStatus().indentLine()); - } - if (!eol.isEmpty() || eof) { - LineWriterOptions::TrailingSpace trailingSpace; - if (!m_currentLine.isEmpty() && m_currentLine.trimmed().isEmpty()) { - // space only line - const Scanner::State &oldState = m_preCachedStatus.lexerState; - if (oldState.isMultilineComment()) - trailingSpace = m_options.commentTrailingSpace; - else if (oldState.isMultiline()) - trailingSpace = m_options.stringTrailingSpace; - else - trailingSpace = m_options.codeTrailingSpace; - // in the LSP we will probably want to treat is specially if it is the line with the - // cursor, of if indentation of it is requested + + if (!eol.isEmpty() || eof) + handleTrailingSpace(); + + // maybe split long line + if (m_options.maxLineLength > 0 && m_currentLine.size() > m_options.maxLineLength) + splitOnMaxLength(eol, eof); + + // maybe write out + if (!eol.isEmpty() || eof) + commitLine(eol); +} + +void IndentingLineWriter::handleTrailingSpace() +{ + LineWriterOptions::TrailingSpace trailingSpace; + if (!m_currentLine.isEmpty() && m_currentLine.trimmed().isEmpty()) { + // space only line + const Scanner::State &oldState = m_preCachedStatus.lexerState; + if (oldState.isMultilineComment()) + trailingSpace = m_options.commentTrailingSpace; + else if (oldState.isMultiline()) + trailingSpace = m_options.stringTrailingSpace; + else + trailingSpace = m_options.codeTrailingSpace; + // in the LSP we will probably want to treat is specially if it is the line with the + // cursor, of if indentation of it is requested + } else { + const Scanner::State ¤tState = fStatus().currentStatus.lexerState; + if (currentState.isMultilineComment()) { + trailingSpace = m_options.commentTrailingSpace; + } else if (currentState.isMultiline()) { + trailingSpace = m_options.stringTrailingSpace; } else { - const Scanner::State ¤tState = fStatus().currentStatus.lexerState; - if (currentState.isMultilineComment()) { + const int kind = + (fStatus().lineTokens.isEmpty() ? Lexer::T_EOL + : fStatus().lineTokens.last().lexKind); + if (Token::lexKindIsComment(kind)) { + // a // comment... trailingSpace = m_options.commentTrailingSpace; - } else if (currentState.isMultiline()) { - trailingSpace = m_options.stringTrailingSpace; + Q_ASSERT(fStatus().currentStatus.state().type + != FormatTextStatus::StateType::MultilineCommentCont + && fStatus().currentStatus.state().type + != FormatTextStatus::StateType:: + MultilineCommentStart); // these should have been + // handled above } else { - const int kind = - (fStatus().lineTokens.isEmpty() ? Lexer::T_EOL - : fStatus().lineTokens.last().lexKind); - if (Token::lexKindIsComment(kind)) { - // a // comment... - trailingSpace = m_options.commentTrailingSpace; - Q_ASSERT(fStatus().currentStatus.state().type - != FormatTextStatus::StateType::MultilineCommentCont - && fStatus().currentStatus.state().type - != FormatTextStatus::StateType:: - MultilineCommentStart); // these should have been - // handled above - } else { - trailingSpace = m_options.codeTrailingSpace; - } + trailingSpace = m_options.codeTrailingSpace; } } - handleTrailingSpace(trailingSpace); } - // maybe split long line - if (m_options.maxLineLength > 0 && m_currentLine.size() > m_options.maxLineLength) { - int possibleSplit = -1; - if (fStatus().lineTokens.size() > 1) { - // {}[] should already be handled (handle also here?) - int minLen = 0; - while (minLen < m_currentLine.size() && m_currentLine.at(minLen).isSpace()) - ++minLen; - minLen = column(minLen) + m_options.minContentLength; - int maxLen = qMax(minLen + m_options.strongMaxLineExtra, m_options.maxLineLength); - std::array<QSet<int>, 2> splitSequence( - { QSet<int>({ // try split after ',','||','&&' - QQmlJSGrammar::T_COMMA, QQmlJSGrammar::T_AND_AND, - QQmlJSGrammar::T_OR_OR }), - QSet<int>({ // try split after '(' - QQmlJSGrammar::T_LPAREN }) }); - // try split after other binary operators? - int minSplit = m_currentLine.size(); - for (const QSet<int> &splitOnToken : splitSequence) { - for (int iToken = 0; iToken < fStatus().tokenCount(); ++iToken) { - const Token t = fStatus().tokenAt(iToken); - int tCol = column(t.end()); - if (splitOnToken.contains(t.lexKind) && tCol > minLen) { - if (tCol <= maxLen && possibleSplit < t.end()) - possibleSplit = t.end(); - if (t.end() < minSplit) - minSplit = t.end(); - } - } - if (possibleSplit > 0) - break; - } - if (possibleSplit == -1 && minSplit + 4 < m_currentLine.size()) - possibleSplit = minSplit; - if (possibleSplit > 0) { - lineChanged(); - quint32 oChange = eolToWrite().size(); - changeAtOffset(m_utf16Offset + possibleSplit, oChange, 0, - 0); // line & col change updated in commitLine - commitLine(eolToWrite(), TextAddType::NewlineSplit, possibleSplit); - shouldReindent = true; - goto indentAgain; - } + LineWriter::handleTrailingSpace(trailingSpace); +} + +void IndentingLineWriter::splitOnMaxLength(const QString &eol, bool eof) +{ + int possibleSplit = -1; + if (fStatus().lineTokens.size() <= 1) + return; + // {}[] should already be handled (handle also here?) + int minLen = 0; + while (minLen < m_currentLine.size() && m_currentLine.at(minLen).isSpace()) + ++minLen; + minLen = column(minLen) + m_options.minContentLength; + int maxLen = qMax(minLen + m_options.strongMaxLineExtra, m_options.maxLineLength); + + // try split after other binary operators? + int minSplit = m_currentLine.size(); + + for (int iToken = 0; iToken < fStatus().tokenCount(); ++iToken) { + const Token t = fStatus().tokenAt(iToken); + int tCol = column(t.end()); + if (splitSequence.contains(t.lexKind) && tCol > minLen) { + if (tCol <= maxLen && possibleSplit < t.end()) + possibleSplit = t.end(); + if (t.end() < minSplit) + minSplit = t.end(); } } - // maybe write out - if (!eol.isEmpty() || eof) - commitLine(eol); + + if (possibleSplit == -1 && minSplit + 4 < m_currentLine.size()) + possibleSplit = minSplit; + if (possibleSplit > 0) { + lineChanged(); + quint32 oChange = eolToWrite().size(); + changeAtOffset(m_utf16Offset + possibleSplit, oChange, 0, + 0); // line & col change updated in commitLine + commitLine(eolToWrite(), TextAddType::NewlineSplit, possibleSplit); + setReindent(true); + reindentAndSplit(eol, eof); + } } } // namespace Dom diff --git a/src/qmldom/qqmldomindentinglinewriter_p.h b/src/qmldom/qqmldomindentinglinewriter_p.h index 63ec3fc432..21197e277a 100644 --- a/src/qmldom/qqmldomindentinglinewriter_p.h +++ b/src/qmldom/qqmldomindentinglinewriter_p.h @@ -41,6 +41,7 @@ public: { } void reindentAndSplit(const QString &eol, bool eof = false) override; + void handleTrailingSpace(); FormatPartialStatus &fStatus(); void lineChanged() override { m_fStatusValid = false; } @@ -48,6 +49,8 @@ public: bool reindent() const { return m_reindent; } void setReindent(bool v) { m_reindent = v; } + void splitOnMaxLength(const QString &eol, bool eof); + private: Q_DISABLE_COPY_MOVE(IndentingLineWriter) protected: diff --git a/src/qmldom/qqmldomlinewriter_p.h b/src/qmldom/qqmldomlinewriter_p.h index 0046e3e31a..05fa3a4399 100644 --- a/src/qmldom/qqmldomlinewriter_p.h +++ b/src/qmldom/qqmldomlinewriter_p.h @@ -82,7 +82,7 @@ public: enum class AttributesSequence { Normalize, Preserve }; Q_ENUM(AttributesSequence) - int maxLineLength = -1; + int maxLineLength = -1; // -1 means no limit int strongMaxLineExtra = 20; int minContentLength = 10; #if defined (Q_OS_WIN) |