Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmldomindentinglinewriter.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
6
7#include <QtCore/QCoreApplication>
8#include <QtCore/QRegularExpression>
9
11namespace QQmlJS {
12namespace Dom {
13
14// If one of these tokens is the split token on a line, the line should be split after it.
15static constexpr bool shouldSplitAfterToken(int kind)
16{
17 switch (kind) {
18 case Lexer::T_COMMA:
19 case Lexer::T_COLON:
20 case Lexer::T_SEMICOLON:
21 case Lexer::T_LBRACE:
22 case Lexer::T_LPAREN:
23 case Lexer::T_LBRACKET:
24 return true;
25 default:
26 break;
27 }
28 return false;
29}
30
32{
33 if (!m_fStatusValid) {
34 m_fStatus = formatCodeLine(m_currentLine, m_options.formatOptions, m_preCachedStatus);
35 m_fStatusValid = true;
36 }
37 return m_fStatus;
38}
39
41{
42 m_preCachedStatus = fStatus().currentStatus;
43}
44
45void IndentingLineWriter::reindentAndSplit(const QString &eol, bool eof)
46{
47 // maybe re-indent
48 if (m_reindent && m_columnNr == 0)
50
51 if (!eol.isEmpty() || eof)
53
54 // maybe split long line
55 if (m_options.maxLineLength > 0 && m_currentLine.size() > m_options.maxLineLength)
56 splitOnMaxLength(eol, eof);
57
58 // maybe write out
59 if (!eol.isEmpty() || eof)
60 commitLine(eol);
61}
62
64{
65 LineWriterOptions::TrailingSpace trailingSpace;
66 if (!m_currentLine.isEmpty() && m_currentLine.trimmed().isEmpty()) {
67 // space only line
68 const Scanner::State &oldState = m_preCachedStatus.lexerState;
69 if (oldState.isMultilineComment())
70 trailingSpace = m_options.commentTrailingSpace;
71 else if (oldState.isMultiline())
72 trailingSpace = m_options.stringTrailingSpace;
73 else
74 trailingSpace = m_options.codeTrailingSpace;
75 // in the LSP we will probably want to treat is specially if it is the line with the
76 // cursor, of if indentation of it is requested
77 } else {
78 const Scanner::State &currentState = fStatus().currentStatus.lexerState;
79 if (currentState.isMultilineComment()) {
80 trailingSpace = m_options.commentTrailingSpace;
81 } else if (currentState.isMultiline()) {
82 trailingSpace = m_options.stringTrailingSpace;
83 } else {
84 const int kind =
85 (fStatus().lineTokens.isEmpty() ? Lexer::T_EOL
86 : fStatus().lineTokens.last().lexKind);
88 // a // comment...
89 trailingSpace = m_options.commentTrailingSpace;
90 Q_ASSERT(fStatus().currentStatus.state().type
91 != FormatTextStatus::StateType::MultilineCommentCont
92 && fStatus().currentStatus.state().type
93 != FormatTextStatus::StateType::
94 MultilineCommentStart); // these should have been
95 // handled above
96 } else {
97 trailingSpace = m_options.codeTrailingSpace;
98 }
99 }
100 }
101 LineWriter::handleTrailingSpace(trailingSpace);
102}
103
104int IndentingLineWriter::findSplitLocation(const QList<Token> &tokens, int minSplitLength)
105{
106 // Reverse search to find the "last"
107 auto lastDelimiterTokenBeforeLineSplitIt =
108 std::find_if(tokens.crbegin(), tokens.crend(), [&](auto &&t) {
109 return Token::lexKindIsDelimiter(t.lexKind)
110 && column(t.end()) >= minSplitLength;
111 });
112
113 if (lastDelimiterTokenBeforeLineSplitIt == tokens.crend())
114 return -1;
115
116 if (shouldSplitAfterToken(lastDelimiterTokenBeforeLineSplitIt->lexKind)) {
117 return lastDelimiterTokenBeforeLineSplitIt->end();
118 } else {
119 // split before the token (after the previous token)
120 auto previousTokenIt = std::next(lastDelimiterTokenBeforeLineSplitIt);
121 return previousTokenIt != tokens.crend() ? previousTokenIt->end()
122 : lastDelimiterTokenBeforeLineSplitIt->begin();
123 }
124}
125
126void IndentingLineWriter::splitOnMaxLength(const QString &eol, bool eof)
127{
128 if (fStatus().lineTokens.size() <= 1)
129 return;
130 // {}[] should already be handled (handle also here?)
131 int minLen = 0;
132 while (minLen < m_currentLine.size() && m_currentLine.at(minLen).isSpace())
133 ++minLen;
134 minLen = column(minLen) + m_options.minContentLength;
135 int possibleSplit = findSplitLocation(fStatus().lineTokens, minLen);
136 if (possibleSplit > 0) {
138 commitLine(eolToWrite(), TextAddType::NewlineSplit, possibleSplit);
139 setReindent(true);
140 reindentAndSplit(eol, eof);
141 }
142}
143
144} // namespace Dom
145} // namespace QQmlJS
146QT_END_NAMESPACE
void splitOnMaxLength(const QString &eol, bool eof)
void setLineIndent(int indentAmount)
static bool lexKindIsComment(int kind)
static constexpr bool shouldSplitAfterToken(int kind)