235 auto enter = [
this](StateType newState) {
this->enterState(newState); };
237 auto leave = [
this](
bool statementDone =
false) {
this->leaveState(statementDone
); };
239 auto turnInto = [
this](StateType newState) {
this->turnIntoState(newState); };
241 qCDebug(formatterLog) <<
"Starting to look at " << line;
243 for (; tokenIndex < lineTokens.size();) {
245 const int kind = currentToken.lexKind;
247 qCDebug(formatterLog) <<
"Token: " << tokenText(currentToken);
249 if (Token::lexKindIsComment(kind)
250 && currentStatus.state().type != StateType::MultilineCommentCont
251 && currentStatus.state().type != StateType::MultilineCommentStart) {
256 switch (currentStatus.state().type) {
257 case StateType::TopmostIntro:
259 case QQmlJSGrammar::T_IDENTIFIER:
260 enter(StateType::ObjectdefinitionOrJs);
262 case QQmlJSGrammar::T_IMPORT:
263 enter(StateType::TopQml);
265 case QQmlJSGrammar::T_LBRACE:
266 enter(StateType::TopJs);
267 enter(StateType::Expression);
270 enter(StateType::TopJs);
275 case StateType::TopQml:
277 case QQmlJSGrammar::T_IMPORT:
278 enter(StateType::ImportStart);
280 case QQmlJSGrammar::T_IDENTIFIER:
281 enter(StateType::BindingOrObjectdefinition);
284 if (Token::lexKindIsIdentifier(kind))
285 enter(StateType::BindingOrObjectdefinition);
290 case StateType::TopJs:
294 case StateType::ObjectdefinitionOrJs:
296 case QQmlJSGrammar::T_DOT:
298 case QQmlJSGrammar::T_LBRACE:
299 turnInto(StateType::BindingOrObjectdefinition);
302 if (!Token::lexKindIsIdentifier(kind) || !line.at(currentToken.begin()).isUpper()) {
303 turnInto(StateType::TopJs);
309 case StateType::ImportStart:
310 enter(StateType::ImportMaybeDotOrVersionOrAs);
313 case StateType::ImportMaybeDotOrVersionOrAs:
315 case QQmlJSGrammar::T_DOT:
316 turnInto(StateType::ImportDot);
318 case QQmlJSGrammar::T_AS:
319 turnInto(StateType::ImportAs);
321 case QQmlJSGrammar::T_NUMERIC_LITERAL:
322 case QQmlJSGrammar::T_VERSION_NUMBER:
323 turnInto(StateType::ImportMaybeAs);
332 case StateType::ImportMaybeAs:
334 case QQmlJSGrammar::T_AS:
335 turnInto(StateType::ImportAs);
344 case StateType::ImportDot:
346 turnInto(StateType::ImportMaybeDotOrVersionOrAs);
354 case StateType::ImportAs:
361 case StateType::BindingOrObjectdefinition:
363 case QQmlJSGrammar::T_COLON:
364 enter(StateType::BindingAssignment);
366 case QQmlJSGrammar::T_LBRACE:
367 enter(StateType::ObjectdefinitionOpen);
372 case StateType::BindingAssignment:
374 case QQmlJSGrammar::T_AUTOMATIC_SEMICOLON:
375 case QQmlJSGrammar::T_COMPATIBILITY_SEMICOLON:
376 case QQmlJSGrammar::T_SEMICOLON:
379 case QQmlJSGrammar::T_IF:
380 enter(StateType::IfStatement);
382 case QQmlJSGrammar::T_WITH:
383 enter(StateType::StatementWithCondition);
385 case QQmlJSGrammar::T_TRY:
386 enter(StateType::TryStatement);
388 case QQmlJSGrammar::T_SWITCH:
389 enter(StateType::SwitchStatement);
391 case QQmlJSGrammar::T_LBRACE:
392 enter(StateType::JsblockOpen);
394 case QQmlJSGrammar::T_ON:
395 case QQmlJSGrammar::T_AS:
396 case QQmlJSGrammar::T_IMPORT:
397 case QQmlJSGrammar::T_SIGNAL:
398 case QQmlJSGrammar::T_PROPERTY:
399 case QQmlJSGrammar::T_REQUIRED:
400 case QQmlJSGrammar::T_READONLY:
401 case QQmlJSGrammar::T_IDENTIFIER:
402 enter(StateType::ExpressionOrObjectdefinition);
406 case QQmlJSGrammar::T_RBRACKET:
407 case QQmlJSGrammar::T_RPAREN:
412 enter(StateType::Expression);
417 case StateType::ObjectdefinitionOpen:
419 case QQmlJSGrammar::T_RBRACE:
422 case QQmlJSGrammar::T_DEFAULT:
423 case QQmlJSGrammar::T_READONLY:
424 enter(StateType::PropertyModifiers);
426 case QQmlJSGrammar::T_PROPERTY:
427 enter(StateType::PropertyStart);
429 case QQmlJSGrammar::T_REQUIRED:
430 enter(StateType::RequiredProperty);
432 case QQmlJSGrammar::T_COMPONENT:
433 enter(StateType::ComponentStart);
435 case QQmlJSGrammar::T_FUNCTION:
436 enter(StateType::FunctionStart);
438 case QQmlJSGrammar::T_SIGNAL:
439 enter(StateType::SignalStart);
441 case QQmlJSGrammar::T_ENUM:
442 enter(StateType::EnumStart);
444 case QQmlJSGrammar::T_ON:
445 case QQmlJSGrammar::T_AS:
446 case QQmlJSGrammar::T_IMPORT:
447 enter(StateType::BindingOrObjectdefinition);
450 if (Token::lexKindIsIdentifier(kind))
451 enter(StateType::BindingOrObjectdefinition);
456 case StateType::PropertyModifiers:
458 case QQmlJSGrammar::T_PROPERTY:
459 turnInto(StateType::PropertyStart);
461 case QQmlJSGrammar::T_DEFAULT:
462 case QQmlJSGrammar::T_READONLY:
464 case QQmlJSGrammar::T_REQUIRED:
465 turnInto(StateType::RequiredProperty);
473 case StateType::PropertyStart:
475 case QQmlJSGrammar::T_COLON:
476 enter(StateType::BindingAssignment);
478 case QQmlJSGrammar::T_VAR:
479 case QQmlJSGrammar::T_IDENTIFIER:
480 enter(StateType::PropertyName);
484 if (kindIsIdentifier && tokenText(currentToken) == u"list") {
485 enter(StateType::PropertyListOpen);
486 }
else if (kindIsIdentifier) {
487 enter(StateType::PropertyName);
495 case StateType::RequiredProperty:
497 case QQmlJSGrammar::T_PROPERTY:
498 turnInto(StateType::PropertyStart);
500 case QQmlJSGrammar::T_DEFAULT:
501 case QQmlJSGrammar::T_READONLY:
502 turnInto(StateType::PropertyModifiers);
504 case QQmlJSGrammar::T_IDENTIFIER:
513 case StateType::ComponentStart:
515 case QQmlJSGrammar::T_IDENTIFIER:
516 turnInto(StateType::ComponentName);
524 case StateType::ComponentName:
526 case QQmlJSGrammar::T_COLON:
527 enter(StateType::BindingAssignment);
535 case StateType::PropertyName:
536 turnInto(StateType::PropertyMaybeInitializer);
539 case StateType::PropertyListOpen: {
540 const QStringView tok = tokenText(currentToken);
542 turnInto(StateType::PropertyName);
545 case StateType::PropertyMaybeInitializer:
547 case QQmlJSGrammar::T_COLON:
548 turnInto(StateType::BindingAssignment);
556 case StateType::EnumStart:
558 case QQmlJSGrammar::T_LBRACE:
559 enter(StateType::ObjectliteralOpen);
564 case StateType::SignalStart:
566 case QQmlJSGrammar::T_COLON:
567 enter(StateType::BindingAssignment);
570 enter(StateType::SignalMaybeArglist);
575 case StateType::SignalMaybeArglist:
577 case QQmlJSGrammar::T_LPAREN:
578 turnInto(StateType::SignalArglistOpen);
586 case StateType::SignalArglistOpen:
588 case QQmlJSGrammar::T_RPAREN:
594 case StateType::FunctionStart:
596 case QQmlJSGrammar::T_LPAREN:
597 enter(StateType::FunctionArglistOpen);
602 case StateType::FunctionArglistOpen:
604 case QQmlJSGrammar::T_COLON:
605 enter(StateType::TypeAnnotation);
607 case QQmlJSGrammar::T_RPAREN:
608 turnInto(StateType::FunctionArglistClosed);
613 case StateType::FunctionArglistClosed:
615 case QQmlJSGrammar::T_COLON:
616 enter(StateType::TypeAnnotation);
618 case QQmlJSGrammar::T_LBRACE:
619 turnInto(StateType::JsblockOpen);
627 case StateType::TypeAnnotation:
629 case QQmlJSGrammar::T_IDENTIFIER:
630 case QQmlJSGrammar::T_DOT:
632 case QQmlJSGrammar::T_LT:
633 turnInto(StateType::TypeParameter);
641 case StateType::TypeParameter:
643 case QQmlJSGrammar::T_LT:
644 enter(StateType::TypeParameter);
646 case QQmlJSGrammar::T_GT:
652 case StateType::ExpressionOrObjectdefinition:
654 case QQmlJSGrammar::T_DOT:
657 case QQmlJSGrammar::T_LBRACE:
658 turnInto(StateType::ObjectdefinitionOpen);
662 case QQmlJSGrammar::T_RBRACKET:
663 case QQmlJSGrammar::T_RPAREN:
671 enter(StateType::Expression);
676 case StateType::ExpressionOrLabel:
678 case QQmlJSGrammar::T_COLON:
679 turnInto(StateType::LabelledStatement);
683 case QQmlJSGrammar::T_RBRACKET:
684 case QQmlJSGrammar::T_RPAREN:
689 enter(StateType::Expression);
694 case StateType::TernaryOp:
695 if (kind == QQmlJSGrammar::T_COLON) {
696 enter(StateType::TernaryOpAfterColon);
697 enter(StateType::ExpressionContinuation);
701 case StateType::TernaryOpAfterColon:
702 case StateType::Expression:
706 case QQmlJSGrammar::T_COMMA:
709 case QQmlJSGrammar::T_RBRACKET:
710 case QQmlJSGrammar::T_RPAREN:
713 case QQmlJSGrammar::T_RBRACE:
716 case QQmlJSGrammar::T_AUTOMATIC_SEMICOLON:
717 case QQmlJSGrammar::T_COMPATIBILITY_SEMICOLON:
718 case QQmlJSGrammar::T_SEMICOLON:
722 if (Token::lexKindIsDelimiter(kind))
723 enter(StateType::ExpressionContinuation);
728 case StateType::ExpressionContinuation:
732 case StateType::ExpressionMaybeContinuation:
734 case QQmlJSGrammar::T_QUESTION:
735 case QQmlJSGrammar::T_LBRACKET:
736 case QQmlJSGrammar::T_LPAREN:
737 case QQmlJSGrammar::T_LBRACE:
741 leave(!Token::lexKindIsDelimiter(kind));
746 case StateType::ParenOpen:
750 case QQmlJSGrammar::T_RPAREN:
756 case StateType::BracketOpen:
760 case QQmlJSGrammar::T_COMMA:
761 enter(StateType::BracketElementStart);
763 case QQmlJSGrammar::T_RBRACKET:
769 case StateType::ObjectliteralOpen:
773 case QQmlJSGrammar::T_COLON:
774 enter(StateType::ObjectliteralAssignment);
776 case QQmlJSGrammar::T_RBRACKET:
777 case QQmlJSGrammar::T_RPAREN:
780 case QQmlJSGrammar::T_RBRACE:
787 case StateType::ObjectliteralAssignment:
791 case QQmlJSGrammar::T_COMMA:
794 case QQmlJSGrammar::T_RBRACKET:
795 case QQmlJSGrammar::T_RPAREN:
798 case QQmlJSGrammar::T_RBRACE:
802 if (Token::lexKindIsDelimiter(kind))
803 enter(StateType::ExpressionContinuation);
808 case StateType::BracketElementStart:
810 turnInto(StateType::BracketElementMaybeObjectdefinition);
817 case StateType::BracketElementMaybeObjectdefinition:
819 case QQmlJSGrammar::T_LBRACE:
820 turnInto(StateType::ObjectdefinitionOpen);
828 case StateType::JsblockOpen:
829 case StateType::SubstatementOpen:
833 case QQmlJSGrammar::T_RBRACE:
839 case StateType::LabelledStatement:
845 case StateType::Substatement:
847 if (kind != QQmlJSGrammar::T_LBRACE) {
852 case QQmlJSGrammar::T_LBRACE:
853 turnInto(StateType::SubstatementOpen);
858 case StateType::IfStatement:
860 case QQmlJSGrammar::T_LPAREN:
861 enter(StateType::ConditionOpen);
869 case StateType::MaybeElse:
871 case QQmlJSGrammar::T_ELSE:
872 turnInto(StateType::ElseClause);
873 enter(StateType::Substatement);
881 case StateType::MaybeCatchOrFinally:
883 case QQmlJSGrammar::T_CATCH:
884 turnInto(StateType::CatchStatement);
886 case QQmlJSGrammar::T_FINALLY:
887 turnInto(StateType::FinallyStatement);
895 case StateType::ElseClause:
902 case StateType::ConditionOpen:
906 case QQmlJSGrammar::T_RPAREN:
907 turnInto(StateType::Substatement);
912 case StateType::SwitchStatement:
913 case StateType::CatchStatement:
914 case StateType::StatementWithCondition:
916 case QQmlJSGrammar::T_LPAREN:
917 enter(StateType::StatementWithConditionParenOpen);
924 case StateType::StatementWithConditionParenOpen:
928 case QQmlJSGrammar::T_RPAREN:
929 turnInto(StateType::Substatement);
934 case StateType::TryStatement:
935 case StateType::FinallyStatement:
937 case QQmlJSGrammar::T_LBRACE:
938 enter(StateType::JsblockOpen);
946 case StateType::DoStatement:
948 case QQmlJSGrammar::T_WHILE:
950 case QQmlJSGrammar::T_LPAREN:
951 enter(StateType::DoStatementWhileParenOpen);
959 case StateType::DoStatementWhileParenOpen:
963 case QQmlJSGrammar::T_RPAREN:
970 case StateType::BreakcontinueStatement:
979 case StateType::CaseStart:
981 case QQmlJSGrammar::T_COLON:
982 turnInto(StateType::CaseCont);
987 case StateType::CaseCont:
988 if (kind != QQmlJSGrammar::T_CASE && kind != QQmlJSGrammar::T_DEFAULT && tryStatement())
991 case QQmlJSGrammar::T_RBRACE:
994 case QQmlJSGrammar::T_DEFAULT:
995 case QQmlJSGrammar::T_CASE:
1001 case StateType::MultilineCommentStart:
1002 case StateType::MultilineCommentCont:
1006 }
else if (tokenIndex == lineTokens.size() - 1
1007 && !currentStatus.lexerState.isMultiline()) {
1011 turnInto(StateType::MultilineCommentCont);
1016 qWarning() <<
"Unhandled state" << currentStatus.state().typeStr();
1023 StateType topState = currentStatus.state().type;
1026 if (topState == StateType::ExpressionOrLabel)
1027 enterState(StateType::Expression);
1029 else if (topState == StateType::BreakcontinueStatement)
1032 topState = currentStatus.state().type;
1035 if (topState == StateType::Expression || topState == StateType::ExpressionOrObjectdefinition
1036 || topState == StateType::ObjectliteralAssignment
1037 || topState == StateType::TernaryOpAfterColon) {
1038 enterState(StateType::ExpressionMaybeContinuation);
1041 if (topState != StateType::MultilineCommentStart && topState != StateType::MultilineCommentCont
1042 && currentStatus.lexerState.state.tokenKind == QQmlJSGrammar::T_PARTIAL_COMMENT) {
1043 enterState(StateType::MultilineCommentStart);
1045 currentStatus.finalIndent = currentIndent;
1058 if (topState.type == StateType::MultilineCommentStart
1059 || topState.type == StateType::MultilineCommentCont) {
1064 if (oldStatus.lexerState.state.tokenKind == QQmlJSGrammar::T_PARTIAL_DOUBLE_QUOTE_STRING_LITERAL
1065 || oldStatus.lexerState.state.tokenKind == QQmlJSGrammar::T_PARTIAL_SINGLE_QUOTE_STRING_LITERAL
1066 || oldStatus.lexerState.state.tokenKind == QQmlJSGrammar::T_PARTIAL_TEMPLATE_HEAD
1067 || oldStatus.lexerState.state.tokenKind == QQmlJSGrammar::T_PARTIAL_TEMPLATE_MIDDLE) {
1071 switch (tokenKind) {
1072 case QQmlJSGrammar::T_LBRACE:
1073 if (topState.type == StateType::Substatement
1074 || topState.type == StateType::BindingAssignment
1075 || topState.type == StateType::CaseCont) {
1076 return topState.savedIndentDepth;
1079 case QQmlJSGrammar::T_RBRACE: {
1080 if (topState.type == StateType::JsblockOpen && previousState.type == StateType::CaseCont) {
1081 return previousState.savedIndentDepth;
1083 for (
int i = 0; oldStatus.state(i).type != StateType::TopmostIntro; ++i) {
1084 const StateType type = oldStatus
.state(i
).type;
1085 if (type == StateType::ObjectdefinitionOpen || type == StateType::JsblockOpen
1086 || type == StateType::SubstatementOpen || type == StateType::ObjectliteralOpen) {
1087 return oldStatus
.state(i
).savedIndentDepth;
1092 case QQmlJSGrammar::T_RBRACKET:
1093 for (
int i = 0; oldStatus.state(i).type != StateType::TopmostIntro; ++i) {
1094 const StateType type = oldStatus
.state(i
).type;
1095 if (type == StateType::BracketOpen) {
1096 return oldStatus
.state(i
).savedIndentDepth;
1100 case QQmlJSGrammar::T_LBRACKET:
1101 case QQmlJSGrammar::T_LPAREN:
1102 if (topState.type == StateType::ExpressionMaybeContinuation)
1103 return topState.savedIndentDepth;
1105 case QQmlJSGrammar::T_ELSE:
1106 if (topState.type == StateType::MaybeElse) {
1107 return oldStatus
.state(1
).savedIndentDepth;
1108 }
else if (topState.type == StateType::ExpressionMaybeContinuation) {
1109 bool hasElse =
false;
1110 for (
int i = 1; oldStatus.state(i).type != StateType::TopmostIntro; ++i) {
1111 const StateType type = oldStatus
.state(i
).type;
1112 if (type == StateType::ElseClause)
1114 if (type == StateType::IfStatement) {
1118 return oldStatus
.state(i
).savedIndentDepth;
1124 case QQmlJSGrammar::T_CATCH:
1125 case QQmlJSGrammar::T_FINALLY:
1126 if (topState.type == StateType::MaybeCatchOrFinally)
1127 return oldStatus
.state(1
).savedIndentDepth;
1129 case QQmlJSGrammar::T_COLON:
1130 if (topState.type == StateType::TernaryOp)
1131 return indentDepth - 2;
1133 case QQmlJSGrammar::T_QUESTION:
1134 if (topState.type == StateType::ExpressionMaybeContinuation)
1135 return topState.savedIndentDepth;
1138 case QQmlJSGrammar::T_DEFAULT:
1139 case QQmlJSGrammar::T_CASE:
1140 for (
int i = 0; oldStatus.state(i).type != StateType::TopmostIntro; ++i) {
1141 const StateType type = oldStatus
.state(i
).type;
1142 if (type == StateType::SwitchStatement || type == StateType::CaseCont) {
1143 return oldStatus
.state(i
).savedIndentDepth;
1144 }
else if (type == StateType::TopmostIntro) {
1150 if (Token::lexKindIsDelimiter(tokenKind)
1151 && topState.type == StateType::ExpressionMaybeContinuation)
1152 return topState.savedIndentDepth;
1206 int *savedIndentDepth)
const
1208 const State &parentState = currentStatus.state();
1212 const bool lastToken = (tokenIndex == lineTokens.size() - 1);
1215 case StateType::ObjectdefinitionOpen: {
1217 if (parentState.type == StateType::BindingAssignment)
1218 *savedIndentDepth = currentStatus.state(1).savedIndentDepth;
1221 *savedIndentDepth = tokenPosition;
1227 case StateType::BindingOrObjectdefinition:
1229 *indentDepth = *savedIndentDepth = tokenPosition;
1232 case StateType::BindingAssignment:
1233 case StateType::ObjectliteralAssignment:
1240 case StateType::ExpressionOrObjectdefinition:
1241 *indentDepth = tokenPosition;
1244 case StateType::ExpressionOrLabel:
1245 if (*indentDepth == tokenPosition)
1248 *indentDepth = tokenPosition;
1251 case StateType::Expression:
1252 if (*indentDepth == tokenPosition) {
1255 if (parentState.type != StateType::ExpressionOrObjectdefinition
1256 && parentState.type != StateType::ExpressionOrLabel
1257 && parentState.type != StateType::BindingAssignment) {
1263 else if (parentState.type != StateType::ExpressionOrObjectdefinition
1264 && parentState.type != StateType::ExpressionOrLabel) {
1265 *indentDepth = tokenPosition;
1269 case StateType::ExpressionMaybeContinuation:
1271 for (
int i = 1; currentStatus.state(i).type != StateType::TopmostIntro; ++i) {
1272 const StateType type = currentStatus.state(i).type;
1273 if (FormatTextStatus::isExpressionEndState(type)
1274 && !FormatTextStatus::isBracelessState(type)) {
1275 *indentDepth = currentStatus.state(i - 1).savedIndentDepth;
1281 case StateType::BracketOpen:
1282 if (parentState.type == StateType::Expression
1283 && currentStatus.state(1).type == StateType::BindingAssignment) {
1284 *savedIndentDepth = currentStatus.state(2).savedIndentDepth;
1286 }
else if (parentState.type == StateType::ObjectliteralAssignment) {
1287 *savedIndentDepth = parentState.savedIndentDepth;
1289 }
else if (!lastToken) {
1290 *indentDepth = tokenPosition + 1;
1296 case StateType::FunctionStart:
1301 case StateType::DoStatementWhileParenOpen:
1302 case StateType::StatementWithConditionParenOpen:
1303 case StateType::SignalArglistOpen:
1304 case StateType::FunctionArglistOpen:
1305 case StateType::ParenOpen:
1307 *indentDepth = tokenPosition + 1;
1312 case StateType::TernaryOp:
1314 *indentDepth = tokenPosition + tk
.length + 1;
1319 case StateType::JsblockOpen:
1321 if (parentState.type == StateType::CaseCont) {
1322 *savedIndentDepth = parentState.savedIndentDepth;
1326 case StateType::SubstatementOpen:
1328 if (parentState.type == StateType::BindingAssignment)
1329 *savedIndentDepth = currentStatus.state(1).savedIndentDepth;
1333 case StateType::Substatement:
1337 case StateType::ObjectliteralOpen:
1338 if (parentState.type == StateType::Expression
1339 || parentState.type == StateType::ObjectliteralAssignment) {
1341 if (currentStatus.state(1).type == StateType::ExpressionOrLabel)
1342 *indentDepth = currentStatus.state(1).savedIndentDepth;
1344 *indentDepth = parentState.savedIndentDepth;
1345 *savedIndentDepth = *indentDepth;
1350 case StateType::StatementWithCondition:
1351 case StateType::TryStatement:
1352 case StateType::CatchStatement:
1353 case StateType::FinallyStatement:
1354 case StateType::IfStatement:
1355 case StateType::DoStatement:
1356 case StateType::SwitchStatement:
1357 if (firstToken || parentState.type == StateType::BindingAssignment)
1358 *savedIndentDepth = tokenPosition;
1360 *indentDepth = *savedIndentDepth;
1362 if (!firstToken && newState == StateType::IfStatement
1363 && parentState.type == StateType::Substatement
1364 && currentStatus.state(1).type == StateType::ElseClause) {
1365 *indentDepth = currentStatus.state(1).savedIndentDepth;
1366 *savedIndentDepth = *indentDepth;
1370 case StateType::MaybeElse:
1371 case StateType::MaybeCatchOrFinally: {
1373 int lastNonEndState = 0;
1374 while (!FormatTextStatus::isExpressionEndState(
1375 currentStatus.state(lastNonEndState + 1).type))
1377 *indentDepth = currentStatus.state(lastNonEndState).savedIndentDepth;
1381 case StateType::ConditionOpen:
1386 *indentDepth = tokenPosition + 1;
1389 case StateType::CaseStart:
1390 *savedIndentDepth = tokenPosition;
1393 case StateType::CaseCont:
1397 case StateType::MultilineCommentStart:
1398 *indentDepth = tokenPosition + 2;
1401 case StateType::MultilineCommentCont:
1402 *indentDepth = tokenPosition;