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
qqmldomcodeformatter_p.h
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// Qt-Security score:significant
4
5#ifndef QQMLDOMCODEFORMATTER_P_H
6#define QQMLDOMCODEFORMATTER_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include "qqmldom_global.h"
23
24#include <QtCore/QStack>
25#include <QtCore/QList>
26#include <QtCore/QSet>
27#include <QtCore/QMetaObject>
28
30
31namespace QQmlJS {
32namespace Dom {
33
35{
37public:
38 enum class StateType : quint8 {
40
41 TopmostIntro, // The first line in a "topmost" definition.
42
43 TopQml, // root state for qml
44 TopJs, // root for js
45 ObjectdefinitionOrJs, // file starts with identifier
46
49
50 PragmaStart, // after 'pragma'
51 PragmaMaybeValue, // after pragma name
52 PragmaValue, // after ':' or ','
53 PragmaMaybeMoreValues, // after pragma value
54
55 ImportStart, // after 'import'
56 ImportMaybeDotOrVersionOrAs, // after string or identifier
57 ImportDot, // after .
58 ImportMaybeAs, // after version
60
61 PropertyStart, // after 'property'
62 PropertyModifiers, // after 'default' or readonly
63 RequiredProperty, // after required
64 PropertyListOpen, // after 'list' as a type
65 PropertyName, // after the type
66 PropertyMaybeInitializer, // after the identifier
67 ComponentStart, // after component
68 ComponentName, // after component Name
69
70 TypeAnnotation, // after a : starting a type annotation
71 TypeParameter, // after a < in a type annotation (starting type parameters)
72
73 EnumStart, // after 'enum'
74
75 SignalStart, // after 'signal'
76 SignalMaybeArglist, // after identifier
77 SignalArglistOpen, // after '('
78
79 LambdaStart, // after '=>'
80 FunctionStart, // after 'function'
81 FunctionArglistOpen, // after '(' starting function argument list
82 FunctionArglistClosed, // after ')' in argument list, expecting '{'
83
84 BindingOrObjectdefinition, // after an identifier
85
86 BindingAssignment, // after : in a binding
88
90 ExpressionContinuation, // at the end of the line, when the next line definitely is a
91 // continuation
92 ExpressionMaybeContinuation, // at the end of the line, when the next line may be an
93 // expression
94 ExpressionOrObjectdefinition, // after a binding starting with an identifier ("x: foo")
95 ExpressionOrLabel, // when expecting a statement and getting an identifier
96
97 ParenOpen, // opening ( in expression
98 BracketOpen, // opening [ in expression
99 ObjectliteralOpen, // opening { in expression
100
101 ObjectliteralAssignment, // after : in object literal
102
103 BracketElementStart, // after starting bracket_open or after ',' in bracket_open
104 BracketElementMaybeObjectdefinition, // after an identifier in bracket_element_start
105
106 TernaryOp, // The ? : operator
107 TernaryOpAfterColon, // after the : in a ternary
108
110
111 EmptyStatement, // for a ';', will be popped directly
112 BreakcontinueStatement, // for continue/break, may be followed by identifier
113
114 IfStatement, // After 'if'
115 MaybeElse, // after the first substatement in an if
116 ElseClause, // The else line of an if-else construct.
117
118 ConditionOpen, // Start of a condition in 'if', 'while', entered after opening paren
119
120 Substatement, // The first line after a conditional or loop construct.
121 SubstatementOpen, // The brace that opens a substatement block.
122
123 LabelledStatement, // after a label
124
125 ReturnStatement, // After 'return'
126 ThrowStatement, // After 'throw'
127
128 StatementWithCondition, // After the 'for', 'while', ... token
129 StatementWithConditionParenOpen, // While inside the (...)
130
131 TryStatement, // after 'try'
132 CatchStatement, // after 'catch', nested in try_statement
133 FinallyStatement, // after 'finally', nested in try_statement
134 MaybeCatchOrFinally, // after ther closing '}' of try_statement and catch_statement,
135 // nested in try_statement
136
137 DoStatement, // after 'do'
138 DoStatementWhileParenOpen, // after '(' in while clause
139
140 SwitchStatement, // After 'switch' token
141 CaseStart, // after a 'case' or 'default' token
142 CaseCont // after the colon in a case/default
143 };
144 Q_ENUM(StateType)
145
147
148 class State
149 {
150 public:
153 bool operator==(const State &other) const
154 {
155 return type == other.type && savedIndentDepth == other.savedIndentDepth;
156 }
157 QString typeStr() const { return FormatTextStatus::stateToString(type); }
158 };
159
160 static bool isBracelessState(StateType type)
161 {
162 return type == StateType::IfStatement || type == StateType::ElseClause
163 || type == StateType::Substatement || type == StateType::BindingAssignment
164 || type == StateType::BindingOrObjectdefinition;
165 }
166
167 static bool isExpressionEndState(StateType type)
168 {
169 return type == StateType::TopmostIntro || type == StateType::TopJs
170 || type == StateType::ObjectdefinitionOpen || type == StateType::DoStatement
171 || type == StateType::JsblockOpen || type == StateType::SubstatementOpen
172 || type == StateType::BracketOpen || type == StateType::ParenOpen
173 || type == StateType::CaseCont || type == StateType::ObjectliteralOpen;
174 }
175
176 static FormatTextStatus initialStatus(int baseIndent = 0)
177 {
178 return FormatTextStatus {
179 Scanner::State {},
180 QList<State>({ State { quint16(baseIndent), StateType::TopmostIntro } }), baseIndent
181 };
182 }
183
184 size_t size() const { return states.size(); }
185
186 State state(int belowTop = 0) const;
187
188 void pushState(StateType type, quint16 savedIndentDepth)
189 {
190 states.append(State { savedIndentDepth, type });
191 }
192
194 {
195 if (states.isEmpty()) {
196 Q_ASSERT(false);
197 return State();
198 }
199 State res = states.last();
200 states.removeLast();
201 return res;
202 }
203
206 int finalIndent = 0;
207};
208
210{
212public:
213
217
218 // to determine whether a line was joined, Tokenizer needs a
219 // newline character at the end, lease ensure that line contains it
223 FormatPartialStatus(QStringView line, const FormatOptions &options,
224 const FormatTextStatus &initialStatus)
225 : line(line),
226 options(options),
229 currentIndent(0),
230 tokenIndex(0)
231 {
232 Scanner::State startState = initialStatus.lexerState;
233 currentIndent = initialStatus.finalIndent;
234 Scanner tokenize;
235 lineTokens = tokenize(line, startState);
236 currentStatus.lexerState = tokenize.state();
237 }
238
239 void enterState(FormatTextStatus::StateType newState);
240 void leaveState(bool statementDone);
241 void turnIntoState(FormatTextStatus::StateType newState);
242
243 const Token &tokenAt(int idx) const;
244 int tokenCount() const { return lineTokens.size(); }
245 int column(int index) const;
246 QStringView tokenText(const Token &token) const;
247 void handleTokens();
248
249 bool tryInsideExpression(bool alsoExpression);
250 bool tryStatement();
251
252 void defaultOnEnter(FormatTextStatus::StateType newState, int *indentDepth,
253 int *savedIndentDepth) const;
254
255 int indentLine();
256 int indentForNewLineAfter() const;
257 void recalculateWithIndent(int indent);
258
259 void dump() const;
260
268 int tokenIndex = 0;
269};
270
272 const FormatOptions &options,
273 int token = QQmlJSGrammar::T_ERROR);
274
275QMLDOM_EXPORT FormatPartialStatus formatCodeLine(QStringView line, const FormatOptions &options,
276 const FormatTextStatus &initialStatus);
277
278} // namespace Dom
279} // namespace QQmlJs
280QT_END_NAMESPACE
281#endif // QQMLDOMCODEFORMATTER_P_H
const Token & tokenAt(int idx) const
QStringView tokenText(const Token &token) const
FormatPartialStatus(const FormatPartialStatus &o)=default
FormatPartialStatus & operator=(const FormatPartialStatus &o)=default
void enterState(FormatTextStatus::StateType newState)
bool tryInsideExpression(bool alsoExpression)
void defaultOnEnter(FormatTextStatus::StateType newState, int *indentDepth, int *savedIndentDepth) const
void turnIntoState(FormatTextStatus::StateType newState)
FormatPartialStatus(QStringView line, const FormatOptions &options, const FormatTextStatus &initialStatus)
bool operator==(const State &other) const
static bool isBracelessState(StateType type)
static FormatTextStatus initialStatus(int baseIndent=0)
void pushState(StateType type, quint16 savedIndentDepth)
State state(int belowTop=0) const
static bool isExpressionEndState(StateType type)
static bool lexKindIsIdentifier(int kind)
static bool lexKindIsComment(int kind)
static bool lexKindIsInvalid(int kind)
FormatPartialStatus formatCodeLine(QStringView line, const FormatOptions &options, const FormatTextStatus &initialStatus)
int indentForLineStartingWithToken(const FormatTextStatus &oldStatus, const FormatOptions &, int tokenKind)
FormatTextStatus::State State
Combined button and popup list for selecting options.
QT_BEGIN_NAMESPACE Q_STATIC_LOGGING_CATEGORY(lcSynthesizedIterableAccess, "qt.iterable.synthesized", QtWarningMsg)
#define QMLDOM_EXPORT