41static inline int indentAfterPartialFormatting(
int initialIndent, QStringView code,
42 LineWriterOptions options)
44 FormatTextStatus initialState = FormatTextStatus::initialStatus(initialIndent);
45 FormatPartialStatus partialStatus({}, options.formatOptions, initialState);
46 IndentingLineWriter indentingLineWriter([](QStringView line) { Q_UNUSED(line) }, QString(),
47 options, partialStatus.currentStatus);
48 OutWriter indentTracker(indentingLineWriter);
49 const auto commentLines = code.split(u'\n');
50 for (
const auto &line : commentLines) {
51 if (!line.isEmpty()) {
53 formatCodeLine(line, options.formatOptions, partialStatus.currentStatus);
54 indentTracker.write(line);
58 return indentTracker.indent;
67findOverlappingRegion(
const SourceLocation &loc,
68 const OutWriter::OffsetToDisabledRegionMap &formatDisabledRegions)
71 return formatDisabledRegions.cend();
73 return std::find_if(formatDisabledRegions.cbegin(), formatDisabledRegions.cend(),
74 [&loc](
const auto &it) {
return it.isValid() && overlaps(loc, it); });
77QStringView OutWriter::attachedDisableCode(quint32 offset)
const
79 if (formatDisabledRegions.contains(offset)) {
80 const auto &loc = formatDisabledRegions.value(offset);
81 return code.mid(loc.offset, loc.length);
90void OutWriter::maybeWriteDisabledRegion(
const SourceLocation &loc)
94 if (formatDisabledRegions.isEmpty())
96 if (
const auto foundRegionIt = findOverlappingRegion(loc, formatDisabledRegions);
97 foundRegionIt != formatDisabledRegions.end()) {
98 if (isFormatterEnabled) {
99 writeDisabledRegion(loc);
100 isFormatterEnabled =
false;
103 isFormatterEnabled =
true;
109bool OutWriter::shouldFormat(
const FileLocations::Tree &fLoc, FileLocationRegion region)
111 if (!fLoc || formatDisabledRegions.isEmpty())
112 return isFormatterEnabled;
114 if (
const auto regions = fLoc->info().regions; regions.contains(region)) {
115 isFormatterEnabled = findOverlappingRegion(regions.value(region), formatDisabledRegions)
116 == formatDisabledRegions.end();
118 return isFormatterEnabled;
121void OutWriter::scanFormatDirectives(QStringView code,
const QList<SourceLocation> &comments)
125 const auto shouldScanDirectives = lineWriter.options().attributesSequence
126 != LineWriterOptions::AttributesSequence::Normalize
127 && !lineWriter.options().sortImports;
128 if (!shouldScanDirectives)
131 formatDisabledRegions = QmlFormat::identifyDisabledRegions(code, comments);
139void OutWriter::writeDisabledRegion(
const SourceLocation &loc)
141 const auto disabledCode = attachedDisableCode(loc.offset);
142 int newIndent = indentAfterPartialFormatting(indent, disabledCode, lineWriter.options());
143 lineWriter.ensureNewline();
144 lineWriter.setLineIndent(0);
145 indentNextlines =
false;
146 lineWriter.write(disabledCode);
147 lineWriter.setLineIndent(newIndent);
148 indentNextlines =
true;
151void OutWriter::maybeWriteComment(
const Comment &comment)
153 maybeWriteDisabledRegion(comment.sourceLocation());
155 if (!skipComments && formatterEnabled()) {
156 comment.write(*
this);
160 if (!formatterEnabled()) {
161 auto directive = QmlFormat::directiveFromComment(comment.rawComment());
162 if (directive == QmlFormat::Directive::On)
163 isFormatterEnabled =
true;
186void OutWriter::writePreComment(FileLocationRegion region)
191 const auto &comments = pendingComments.top();
192 if (comments.contains(region)) {
193 const auto attachedComments = comments[region];
194 for (
const auto &comment : attachedComments.preComments())
195 maybeWriteComment(comment);
199void OutWriter::writePostComment(FileLocationRegion region)
204 auto &comments = pendingComments.top();
205 if (comments.contains(region)) {
206 const auto attachedComments = comments[region];
207 for (
const auto &comment : attachedComments.postComments())
208 maybeWriteComment(comment);
209 comments.remove(region);
246OutWriter &OutWriter::writeRegion(
const FileLocations::Tree &fLoc, FileLocationRegion region)
248 using namespace Qt::Literals::StringLiterals;
249 QString codeForRegion;
251 case ComponentKeywordRegion:
252 codeForRegion = u"component"_s;
254 case IdColonTokenRegion:
255 case ColonTokenRegion:
256 codeForRegion = u":"_s;
258 case ImportTokenRegion:
259 codeForRegion = u"import"_s;
262 codeForRegion = u"as"_s;
265 codeForRegion = u"on"_s;
268 codeForRegion = u"id"_s;
270 case LeftBraceRegion:
271 codeForRegion = u"{"_s;
273 case RightBraceRegion:
274 codeForRegion = u"}"_s;
276 case LeftBracketRegion:
277 codeForRegion = u"["_s;
279 case RightBracketRegion:
280 codeForRegion = u"]"_s;
282 case LeftParenthesisRegion:
283 codeForRegion = u"("_s;
285 case RightParenthesisRegion:
286 codeForRegion = u")"_s;
288 case EnumKeywordRegion:
289 codeForRegion = u"enum"_s;
291 case DefaultKeywordRegion:
292 codeForRegion = u"default"_s;
294 case RequiredKeywordRegion:
295 codeForRegion = u"required"_s;
297 case ReadonlyKeywordRegion:
298 codeForRegion = u"readonly"_s;
300 case PropertyKeywordRegion:
301 codeForRegion = u"property"_s;
303 case FunctionKeywordRegion:
304 codeForRegion = u"function"_s;
306 case SignalKeywordRegion:
307 codeForRegion = u"signal"_s;
309 case ReturnKeywordRegion:
310 codeForRegion = u"return"_s;
312 case EllipsisTokenRegion:
313 codeForRegion = u"..."_s;
315 case EqualTokenRegion:
316 codeForRegion = u"="_s;
318 case PragmaKeywordRegion:
319 codeForRegion = u"pragma"_s;
321 case CommaTokenRegion:
322 codeForRegion = u","_s;
324 case ForKeywordRegion:
325 codeForRegion = u"for"_s;
327 case ElseKeywordRegion:
328 codeForRegion = u"else"_s;
330 case DoKeywordRegion:
331 codeForRegion = u"do"_s;
333 case WhileKeywordRegion:
334 codeForRegion = u"while"_s;
336 case TryKeywordRegion:
337 codeForRegion = u"try"_s;
339 case CatchKeywordRegion:
340 codeForRegion = u"catch"_s;
342 case FinallyKeywordRegion:
343 codeForRegion = u"finally"_s;
345 case CaseKeywordRegion:
346 codeForRegion = u"case"_s;
348 case ThrowKeywordRegion:
349 codeForRegion = u"throw"_s;
351 case ContinueKeywordRegion:
352 codeForRegion = u"continue"_s;
354 case BreakKeywordRegion:
355 codeForRegion = u"break"_s;
357 case QuestionMarkTokenRegion:
358 codeForRegion = u"?"_s;
360 case SemicolonTokenRegion:
361 codeForRegion = u";"_s;
363 case IfKeywordRegion:
364 codeForRegion = u"if"_s;
366 case SwitchKeywordRegion:
367 codeForRegion = u"switch"_s;
369 case YieldKeywordRegion:
370 codeForRegion = u"yield"_s;
372 case NewKeywordRegion:
373 codeForRegion = u"new"_s;
375 case ThisKeywordRegion:
376 codeForRegion = u"this"_s;
378 case SuperKeywordRegion:
379 codeForRegion = u"super"_s;
381 case StarTokenRegion:
382 codeForRegion = u"*"_s;
384 case DollarLeftBraceTokenRegion:
385 codeForRegion = u"${"_s;
387 case LeftBacktickTokenRegion:
388 case RightBacktickTokenRegion:
389 codeForRegion = u"`"_s;
391 case VirtualKeywordRegion:
392 codeForRegion = u"virtual"_s;
394 case OverrideKeywordRegion:
395 codeForRegion = u"override"_s;
397 case FinalKeywordRegion:
398 codeForRegion = u"final"_s;
401 case ImportUriRegion:
403 case IdentifierRegion:
404 case PragmaValuesRegion:
407 case TypeIdentifierRegion:
408 case TypeModifierRegion:
409 case FirstSemicolonTokenRegion:
410 case SecondSemicolonRegion:
411 case InOfTokenRegion:
412 case OperatorTokenRegion:
414 case EnumValueRegion:
415 Q_ASSERT_X(
false,
"regionToString",
"Using regionToString on a value or an identifier!");
419 return writeRegion(fLoc, region, codeForRegion);
422OutWriter &OutWriter::writeRegion(
const FileLocations::Tree &fLoc, FileLocationRegion region,
425 writePreComment(region);
426 if (regionDecreasesIndentation(region))
428 if (shouldFormat(fLoc, region))
429 lineWriter.write(toWrite);
430 if (regionIncreasesIndentation(region))
432 writePostComment(region);