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);
245OutWriter &OutWriter::writeRegion(
const FileLocations::Tree &fLoc, FileLocationRegion region)
247 using namespace Qt::Literals::StringLiterals;
248 QString codeForRegion;
250 case ComponentKeywordRegion:
251 codeForRegion = u"component"_s;
253 case IdColonTokenRegion:
254 case ColonTokenRegion:
255 codeForRegion = u":"_s;
257 case ImportTokenRegion:
258 codeForRegion = u"import"_s;
261 codeForRegion = u"as"_s;
264 codeForRegion = u"on"_s;
267 codeForRegion = u"id"_s;
269 case LeftBraceRegion:
270 codeForRegion = u"{"_s;
272 case RightBraceRegion:
273 codeForRegion = u"}"_s;
275 case LeftBracketRegion:
276 codeForRegion = u"["_s;
278 case RightBracketRegion:
279 codeForRegion = u"]"_s;
281 case LeftParenthesisRegion:
282 codeForRegion = u"("_s;
284 case RightParenthesisRegion:
285 codeForRegion = u")"_s;
287 case EnumKeywordRegion:
288 codeForRegion = u"enum"_s;
290 case DefaultKeywordRegion:
291 codeForRegion = u"default"_s;
293 case RequiredKeywordRegion:
294 codeForRegion = u"required"_s;
296 case ReadonlyKeywordRegion:
297 codeForRegion = u"readonly"_s;
299 case PropertyKeywordRegion:
300 codeForRegion = u"property"_s;
302 case FunctionKeywordRegion:
303 codeForRegion = u"function"_s;
305 case SignalKeywordRegion:
306 codeForRegion = u"signal"_s;
308 case ReturnKeywordRegion:
309 codeForRegion = u"return"_s;
311 case EllipsisTokenRegion:
312 codeForRegion = u"..."_s;
314 case EqualTokenRegion:
315 codeForRegion = u"="_s;
317 case PragmaKeywordRegion:
318 codeForRegion = u"pragma"_s;
320 case CommaTokenRegion:
321 codeForRegion = u","_s;
323 case ForKeywordRegion:
324 codeForRegion = u"for"_s;
326 case ElseKeywordRegion:
327 codeForRegion = u"else"_s;
329 case DoKeywordRegion:
330 codeForRegion = u"do"_s;
332 case WhileKeywordRegion:
333 codeForRegion = u"while"_s;
335 case TryKeywordRegion:
336 codeForRegion = u"try"_s;
338 case CatchKeywordRegion:
339 codeForRegion = u"catch"_s;
341 case FinallyKeywordRegion:
342 codeForRegion = u"finally"_s;
344 case CaseKeywordRegion:
345 codeForRegion = u"case"_s;
347 case ThrowKeywordRegion:
348 codeForRegion = u"throw"_s;
350 case ContinueKeywordRegion:
351 codeForRegion = u"continue"_s;
353 case BreakKeywordRegion:
354 codeForRegion = u"break"_s;
356 case QuestionMarkTokenRegion:
357 codeForRegion = u"?"_s;
359 case SemicolonTokenRegion:
360 codeForRegion = u";"_s;
362 case IfKeywordRegion:
363 codeForRegion = u"if"_s;
365 case SwitchKeywordRegion:
366 codeForRegion = u"switch"_s;
368 case YieldKeywordRegion:
369 codeForRegion = u"yield"_s;
371 case NewKeywordRegion:
372 codeForRegion = u"new"_s;
374 case ThisKeywordRegion:
375 codeForRegion = u"this"_s;
377 case SuperKeywordRegion:
378 codeForRegion = u"super"_s;
380 case StarTokenRegion:
381 codeForRegion = u"*"_s;
383 case DollarLeftBraceTokenRegion:
384 codeForRegion = u"${"_s;
386 case LeftBacktickTokenRegion:
387 case RightBacktickTokenRegion:
388 codeForRegion = u"`"_s;
390 case FinalKeywordRegion:
391 codeForRegion = u"final"_s;
394 case ImportUriRegion:
396 case IdentifierRegion:
397 case PragmaValuesRegion:
400 case TypeIdentifierRegion:
401 case TypeModifierRegion:
402 case FirstSemicolonTokenRegion:
403 case SecondSemicolonRegion:
404 case InOfTokenRegion:
405 case OperatorTokenRegion:
407 case EnumValueRegion:
408 Q_ASSERT_X(
false,
"regionToString",
"Using regionToString on a value or an identifier!");
412 return writeRegion(fLoc, region, codeForRegion);
415OutWriter &OutWriter::writeRegion(
const FileLocations::Tree &fLoc, FileLocationRegion region,
418 writePreComment(region);
419 if (regionDecreasesIndentation(region))
421 if (shouldFormat(fLoc, region))
422 lineWriter.write(toWrite);
423 if (regionIncreasesIndentation(region))
425 writePostComment(region);