19static inline OutWriter::RegionToCommentMap extractComments(
const DomItem &it)
21 OutWriter::RegionToCommentMap comments;
22 DomItem commentsField = it.field(Fields::comments);
23 if (
const RegionComments *cRegionsPtr = commentsField.as<RegionComments>()) {
24 comments = cRegionsPtr->regionComments();
42static inline int indentAfterPartialFormatting(
int initialIndent, QStringView code,
43 LineWriterOptions options)
45 FormatTextStatus initialState = FormatTextStatus::initialStatus(initialIndent);
46 FormatPartialStatus partialStatus({}, options.formatOptions, initialState);
47 IndentingLineWriter indentingLineWriter([](QStringView line) { Q_UNUSED(line) }, QString(),
48 options, partialStatus.currentStatus);
49 OutWriter indentTracker(indentingLineWriter);
50 const auto commentLines = code.split(u'\n');
51 for (
const auto &line : commentLines) {
52 if (!line.isEmpty()) {
54 formatCodeLine(line, options.formatOptions, partialStatus.currentStatus);
55 indentTracker.write(line);
59 return indentTracker.indent;
68findOverlappingRegion(
const SourceLocation &loc,
69 const OutWriter::OffsetToDisabledRegionMap &formatDisabledRegions)
72 return formatDisabledRegions.cend();
74 return std::find_if(formatDisabledRegions.cbegin(), formatDisabledRegions.cend(),
75 [&loc](
const auto &it) {
return it.isValid() && overlaps(loc, it); });
78QStringView OutWriter::attachedDisableCode(quint32 offset)
const
80 if (formatDisabledRegions.contains(offset)) {
81 const auto &loc = formatDisabledRegions.value(offset);
82 return code.mid(loc.offset, loc.length);
91void OutWriter::maybeWriteDisabledRegion(
const SourceLocation &loc)
95 if (formatDisabledRegions.isEmpty())
97 if (
const auto foundRegionIt = findOverlappingRegion(loc, formatDisabledRegions);
98 foundRegionIt != formatDisabledRegions.end()) {
99 if (isFormatterEnabled) {
100 writeDisabledRegion(loc);
101 isFormatterEnabled =
false;
104 isFormatterEnabled =
true;
110bool OutWriter::shouldFormat(
const FileLocations::Tree &fLoc, FileLocationRegion region)
112 if (!fLoc || formatDisabledRegions.isEmpty())
113 return isFormatterEnabled;
115 if (
const auto regions = fLoc->info().regions; regions.contains(region)) {
116 isFormatterEnabled = findOverlappingRegion(regions.value(region), formatDisabledRegions)
117 == formatDisabledRegions.end();
119 return isFormatterEnabled;
122void OutWriter::scanFormatDirectives(QStringView code,
const QList<SourceLocation> &comments)
126 const auto shouldScanDirectives = lineWriter.options().attributesSequence
127 != LineWriterOptions::AttributesSequence::Normalize
128 && !lineWriter.options().sortImports;
129 if (!shouldScanDirectives)
132 formatDisabledRegions = QmlFormat::identifyDisabledRegions(code, comments);
140void OutWriter::writeDisabledRegion(
const SourceLocation &loc)
142 const auto disabledCode = attachedDisableCode(loc.offset);
143 int newIndent = indentAfterPartialFormatting(indent, disabledCode, lineWriter.options());
144 lineWriter.ensureNewline();
145 lineWriter.setLineIndent(0);
146 indentNextlines =
false;
147 lineWriter.write(disabledCode);
148 lineWriter.setLineIndent(newIndent);
149 indentNextlines =
true;
152void OutWriter::maybeWriteComment(
const Comment &comment)
154 maybeWriteDisabledRegion(comment.sourceLocation());
156 if (!skipComments && formatterEnabled()) {
157 comment.write(*
this);
161 if (!formatterEnabled()) {
162 auto directive = QmlFormat::directiveFromComment(comment.rawComment());
163 if (directive == QmlFormat::Directive::On)
164 isFormatterEnabled =
true;
187void OutWriter::writePreComment(FileLocationRegion region)
192 const auto &comments = pendingComments.top();
193 if (comments.contains(region)) {
194 const auto attachedComments = comments[region];
195 for (
const auto &comment : attachedComments.preComments())
196 maybeWriteComment(comment);
200void OutWriter::writePostComment(FileLocationRegion region)
205 auto &comments = pendingComments.top();
206 if (comments.contains(region)) {
207 const auto attachedComments = comments[region];
208 for (
const auto &comment : attachedComments.postComments())
209 maybeWriteComment(comment);
210 comments.remove(region);
247OutWriter &OutWriter::writeRegion(
const FileLocations::Tree &fLoc, FileLocationRegion region)
249 using namespace Qt::Literals::StringLiterals;
250 QString codeForRegion;
252 case ComponentKeywordRegion:
253 codeForRegion = u"component"_s;
255 case IdColonTokenRegion:
256 case ColonTokenRegion:
257 codeForRegion = u":"_s;
259 case ImportTokenRegion:
260 codeForRegion = u"import"_s;
263 codeForRegion = u"as"_s;
266 codeForRegion = u"on"_s;
269 codeForRegion = u"id"_s;
271 case LeftBraceRegion:
272 codeForRegion = u"{"_s;
274 case RightBraceRegion:
275 codeForRegion = u"}"_s;
277 case LeftBracketRegion:
278 codeForRegion = u"["_s;
280 case RightBracketRegion:
281 codeForRegion = u"]"_s;
283 case LeftParenthesisRegion:
284 codeForRegion = u"("_s;
286 case RightParenthesisRegion:
287 codeForRegion = u")"_s;
289 case EnumKeywordRegion:
290 codeForRegion = u"enum"_s;
292 case DefaultKeywordRegion:
293 codeForRegion = u"default"_s;
295 case RequiredKeywordRegion:
296 codeForRegion = u"required"_s;
298 case ReadonlyKeywordRegion:
299 codeForRegion = u"readonly"_s;
301 case PropertyKeywordRegion:
302 codeForRegion = u"property"_s;
304 case FunctionKeywordRegion:
305 codeForRegion = u"function"_s;
307 case SignalKeywordRegion:
308 codeForRegion = u"signal"_s;
310 case ReturnKeywordRegion:
311 codeForRegion = u"return"_s;
313 case EllipsisTokenRegion:
314 codeForRegion = u"..."_s;
316 case EqualTokenRegion:
317 codeForRegion = u"="_s;
319 case PragmaKeywordRegion:
320 codeForRegion = u"pragma"_s;
322 case CommaTokenRegion:
323 codeForRegion = u","_s;
325 case ForKeywordRegion:
326 codeForRegion = u"for"_s;
328 case ElseKeywordRegion:
329 codeForRegion = u"else"_s;
331 case DoKeywordRegion:
332 codeForRegion = u"do"_s;
334 case WhileKeywordRegion:
335 codeForRegion = u"while"_s;
337 case TryKeywordRegion:
338 codeForRegion = u"try"_s;
340 case CatchKeywordRegion:
341 codeForRegion = u"catch"_s;
343 case FinallyKeywordRegion:
344 codeForRegion = u"finally"_s;
346 case CaseKeywordRegion:
347 codeForRegion = u"case"_s;
349 case ThrowKeywordRegion:
350 codeForRegion = u"throw"_s;
352 case ContinueKeywordRegion:
353 codeForRegion = u"continue"_s;
355 case BreakKeywordRegion:
356 codeForRegion = u"break"_s;
358 case QuestionMarkTokenRegion:
359 codeForRegion = u"?"_s;
361 case SemicolonTokenRegion:
362 codeForRegion = u";"_s;
364 case IfKeywordRegion:
365 codeForRegion = u"if"_s;
367 case SwitchKeywordRegion:
368 codeForRegion = u"switch"_s;
370 case YieldKeywordRegion:
371 codeForRegion = u"yield"_s;
373 case NewKeywordRegion:
374 codeForRegion = u"new"_s;
376 case ThisKeywordRegion:
377 codeForRegion = u"this"_s;
379 case SuperKeywordRegion:
380 codeForRegion = u"super"_s;
382 case StarTokenRegion:
383 codeForRegion = u"*"_s;
385 case DollarLeftBraceTokenRegion:
386 codeForRegion = u"${"_s;
388 case LeftBacktickTokenRegion:
389 case RightBacktickTokenRegion:
390 codeForRegion = u"`"_s;
392 case VirtualKeywordRegion:
393 codeForRegion = u"virtual"_s;
395 case OverrideKeywordRegion:
396 codeForRegion = u"override"_s;
398 case FinalKeywordRegion:
399 codeForRegion = u"final"_s;
402 case ImportUriRegion:
404 case IdentifierRegion:
405 case PragmaValuesRegion:
408 case TypeIdentifierRegion:
409 case TypeModifierRegion:
410 case FirstSemicolonTokenRegion:
411 case SecondSemicolonRegion:
412 case InOfTokenRegion:
413 case OperatorTokenRegion:
415 case EnumValueRegion:
416 Q_ASSERT_X(
false,
"regionToString",
"Using regionToString on a value or an identifier!");
420 return writeRegion(fLoc, region, codeForRegion);
423OutWriter &OutWriter::writeRegion(
const FileLocations::Tree &fLoc, FileLocationRegion region,
426 writePreComment(region);
427 if (regionDecreasesIndentation(region))
429 if (shouldFormat(fLoc, region))
430 lineWriter.write(toWrite);
431 if (regionIncreasesIndentation(region))
433 writePostComment(region);