diff options
author | Semih Yavuz <[email protected]> | 2024-11-11 15:38:38 +0100 |
---|---|---|
committer | Semih Yavuz <[email protected]> | 2024-12-05 23:24:29 +0100 |
commit | 9f1fca90e7b760f54e5fb5689e662defb669c64b (patch) | |
tree | 7b4929c7496806c0933f85b803f696bc19ee8ca0 | |
parent | 7736fdc9940878ce6bd9fb2f8b053f0b1258156e (diff) |
qmlformat: separate reindentAndSplit's concerns
This also changes the behavior of linebreak by combining the split
sequence in a single set. Prior to this commit, linebreak position was
attempted to be detected for a set of tokens. Then, if there is a left
paranthesis in the same line, that would take the split location.
Now change this logic so that break the line after the last token that
lays on column smaller than the allowed maximum width.
Task-number: QTBUG-113590
Change-Id: Ib0e7291a139265ab9bc09be0c574704da25fd722
Reviewed-by: Sami Shalayel <[email protected]>
-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) |