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/QVector>
28#include <QtCore/QMetaObject>
29
31
32namespace QQmlJS {
33namespace Dom {
34
36{
38public:
39 enum class StateType : quint8 {
41
42 TopmostIntro, // The first line in a "topmost" definition.
43
44 TopQml, // root state for qml
45 TopJs, // root for js
46 ObjectdefinitionOrJs, // file starts with identifier
47
50
51 ImportStart, // after 'import'
52 ImportMaybeDotOrVersionOrAs, // after string or identifier
53 ImportDot, // after .
54 ImportMaybeAs, // after version
56
57 PropertyStart, // after 'property'
58 PropertyModifiers, // after 'default' or readonly
59 RequiredProperty, // after required
60 PropertyListOpen, // after 'list' as a type
61 PropertyName, // after the type
62 PropertyMaybeInitializer, // after the identifier
63 ComponentStart, // after component
64 ComponentName, // after component Name
65
66 TypeAnnotation, // after a : starting a type annotation
67 TypeParameter, // after a < in a type annotation (starting type parameters)
68
69 EnumStart, // after 'enum'
70
71 SignalStart, // after 'signal'
72 SignalMaybeArglist, // after identifier
73 SignalArglistOpen, // after '('
74
75 FunctionStart, // after 'function'
76 FunctionArglistOpen, // after '(' starting function argument list
77 FunctionArglistClosed, // after ')' in argument list, expecting '{'
78
79 BindingOrObjectdefinition, // after an identifier
80
81 BindingAssignment, // after : in a binding
83
85 ExpressionContinuation, // at the end of the line, when the next line definitely is a
86 // continuation
87 ExpressionMaybeContinuation, // at the end of the line, when the next line may be an
88 // expression
89 ExpressionOrObjectdefinition, // after a binding starting with an identifier ("x: foo")
90 ExpressionOrLabel, // when expecting a statement and getting an identifier
91
92 ParenOpen, // opening ( in expression
93 BracketOpen, // opening [ in expression
94 ObjectliteralOpen, // opening { in expression
95
96 ObjectliteralAssignment, // after : in object literal
97
98 BracketElementStart, // after starting bracket_open or after ',' in bracket_open
99 BracketElementMaybeObjectdefinition, // after an identifier in bracket_element_start
100
101 TernaryOp, // The ? : operator
102 TernaryOpAfterColon, // after the : in a ternary
103
105
106 EmptyStatement, // for a ';', will be popped directly
107 BreakcontinueStatement, // for continue/break, may be followed by identifier
108
109 IfStatement, // After 'if'
110 MaybeElse, // after the first substatement in an if
111 ElseClause, // The else line of an if-else construct.
112
113 ConditionOpen, // Start of a condition in 'if', 'while', entered after opening paren
114
115 Substatement, // The first line after a conditional or loop construct.
116 SubstatementOpen, // The brace that opens a substatement block.
117
118 LabelledStatement, // after a label
119
120 ReturnStatement, // After 'return'
121 ThrowStatement, // After 'throw'
122
123 StatementWithCondition, // After the 'for', 'while', ... token
124 StatementWithConditionParenOpen, // While inside the (...)
125
126 TryStatement, // after 'try'
127 CatchStatement, // after 'catch', nested in try_statement
128 FinallyStatement, // after 'finally', nested in try_statement
129 MaybeCatchOrFinally, // after ther closing '}' of try_statement and catch_statement,
130 // nested in try_statement
131
132 DoStatement, // after 'do'
133 DoStatementWhileParenOpen, // after '(' in while clause
134
135 SwitchStatement, // After 'switch' token
136 CaseStart, // after a 'case' or 'default' token
137 CaseCont // after the colon in a case/default
138 };
139 Q_ENUM(StateType)
140
142
143 class State
144 {
145 public:
148 bool operator==(const State &other) const
149 {
150 return type == other.type && savedIndentDepth == other.savedIndentDepth;
151 }
152 QString typeStr() const { return FormatTextStatus::stateToString(type); }
153 };
154
155 static bool isBracelessState(StateType type)
156 {
157 return type == StateType::IfStatement || type == StateType::ElseClause
158 || type == StateType::Substatement || type == StateType::BindingAssignment
159 || type == StateType::BindingOrObjectdefinition;
160 }
161
162 static bool isExpressionEndState(StateType type)
163 {
164 return type == StateType::TopmostIntro || type == StateType::TopJs
165 || type == StateType::ObjectdefinitionOpen || type == StateType::DoStatement
166 || type == StateType::JsblockOpen || type == StateType::SubstatementOpen
167 || type == StateType::BracketOpen || type == StateType::ParenOpen
168 || type == StateType::CaseCont || type == StateType::ObjectliteralOpen;
169 }
170
171 static FormatTextStatus initialStatus(int baseIndent = 0)
172 {
173 return FormatTextStatus {
174 Scanner::State {},
175 QVector<State>({ State { quint16(baseIndent), StateType::TopmostIntro } }), baseIndent
176 };
177 }
178
179 size_t size() const { return states.size(); }
180
181 State state(int belowTop = 0) const;
182
183 void pushState(StateType type, quint16 savedIndentDepth)
184 {
185 states.append(State { savedIndentDepth, type });
186 }
187
189 {
190 if (states.isEmpty()) {
191 Q_ASSERT(false);
192 return State();
193 }
194 State res = states.last();
195 states.removeLast();
196 return res;
197 }
198
201 int finalIndent = 0;
202};
203
205{
207public:
208
212
213 // to determine whether a line was joined, Tokenizer needs a
214 // newline character at the end, lease ensure that line contains it
218 FormatPartialStatus(QStringView line, const FormatOptions &options,
219 const FormatTextStatus &initialStatus)
220 : line(line),
221 options(options),
224 currentIndent(0),
225 tokenIndex(0)
226 {
227 Scanner::State startState = initialStatus.lexerState;
228 currentIndent = initialStatus.finalIndent;
229 Scanner tokenize;
230 lineTokens = tokenize(line, startState);
231 currentStatus.lexerState = tokenize.state();
232 }
233
234 void enterState(FormatTextStatus::StateType newState);
235 void leaveState(bool statementDone);
236 void turnIntoState(FormatTextStatus::StateType newState);
237
238 const Token &tokenAt(int idx) const;
239 int tokenCount() const { return lineTokens.size(); }
240 int column(int index) const;
241 QStringView tokenText(const Token &token) const;
242 void handleTokens();
243
244 bool tryInsideExpression(bool alsoExpression);
245 bool tryStatement();
246
247 void defaultOnEnter(FormatTextStatus::StateType newState, int *indentDepth,
248 int *savedIndentDepth) const;
249
250 int indentLine();
251 int indentForNewLineAfter() const;
252 void recalculateWithIndent(int indent);
253
254 void dump() const;
255
263 int tokenIndex = 0;
264};
265
267 const FormatOptions &options,
268 int token = QQmlJSGrammar::T_ERROR);
269
270QMLDOM_EXPORT FormatPartialStatus formatCodeLine(QStringView line, const FormatOptions &options,
271 const FormatTextStatus &initialStatus);
272
273} // namespace Dom
274} // namespace QQmlJs
275QT_END_NAMESPACE
276#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
Q_STATIC_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core")
#define QMLDOM_EXPORT