4597 lines · cpp
1//===--- Format.cpp - Format C++ code -------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// This file implements functions declared in Format.h. This will be11/// split into separate files as we go.12///13//===----------------------------------------------------------------------===//14 15#include "clang/Format/Format.h"16#include "DefinitionBlockSeparator.h"17#include "IntegerLiteralSeparatorFixer.h"18#include "NamespaceEndCommentsFixer.h"19#include "NumericLiteralCaseFixer.h"20#include "ObjCPropertyAttributeOrderFixer.h"21#include "QualifierAlignmentFixer.h"22#include "SortJavaScriptImports.h"23#include "UnwrappedLineFormatter.h"24#include "UsingDeclarationsSorter.h"25#include "clang/Tooling/Inclusions/HeaderIncludes.h"26#include "llvm/ADT/Sequence.h"27#include <limits>28 29#define DEBUG_TYPE "format-formatter"30 31using clang::format::FormatStyle;32 33LLVM_YAML_IS_SEQUENCE_VECTOR(FormatStyle::RawStringFormat)34 35enum BracketAlignmentStyle : int8_t {36 BAS_Align,37 BAS_DontAlign,38 BAS_AlwaysBreak,39 BAS_BlockIndent40};41 42namespace llvm {43namespace yaml {44template <>45struct ScalarEnumerationTraits<FormatStyle::BreakBeforeNoexceptSpecifierStyle> {46 static void47 enumeration(IO &IO, FormatStyle::BreakBeforeNoexceptSpecifierStyle &Value) {48 IO.enumCase(Value, "Never", FormatStyle::BBNSS_Never);49 IO.enumCase(Value, "OnlyWithParen", FormatStyle::BBNSS_OnlyWithParen);50 IO.enumCase(Value, "Always", FormatStyle::BBNSS_Always);51 }52};53 54template <> struct MappingTraits<FormatStyle::AlignConsecutiveStyle> {55 static void enumInput(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {56 IO.enumCase(Value, "None", FormatStyle::AlignConsecutiveStyle({}));57 IO.enumCase(Value, "Consecutive",58 FormatStyle::AlignConsecutiveStyle(59 {/*Enabled=*/true, /*AcrossEmptyLines=*/false,60 /*AcrossComments=*/false, /*AlignCompound=*/false,61 /*AlignFunctionDeclarations=*/true,62 /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));63 IO.enumCase(Value, "AcrossEmptyLines",64 FormatStyle::AlignConsecutiveStyle(65 {/*Enabled=*/true, /*AcrossEmptyLines=*/true,66 /*AcrossComments=*/false, /*AlignCompound=*/false,67 /*AlignFunctionDeclarations=*/true,68 /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));69 IO.enumCase(Value, "AcrossComments",70 FormatStyle::AlignConsecutiveStyle(71 {/*Enabled=*/true, /*AcrossEmptyLines=*/false,72 /*AcrossComments=*/true, /*AlignCompound=*/false,73 /*AlignFunctionDeclarations=*/true,74 /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));75 IO.enumCase(Value, "AcrossEmptyLinesAndComments",76 FormatStyle::AlignConsecutiveStyle(77 {/*Enabled=*/true, /*AcrossEmptyLines=*/true,78 /*AcrossComments=*/true, /*AlignCompound=*/false,79 /*AlignFunctionDeclarations=*/true,80 /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));81 82 // For backward compatibility.83 IO.enumCase(Value, "true",84 FormatStyle::AlignConsecutiveStyle(85 {/*Enabled=*/true, /*AcrossEmptyLines=*/false,86 /*AcrossComments=*/false, /*AlignCompound=*/false,87 /*AlignFunctionDeclarations=*/true,88 /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));89 IO.enumCase(Value, "false", FormatStyle::AlignConsecutiveStyle({}));90 }91 92 static void mapping(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {93 IO.mapOptional("Enabled", Value.Enabled);94 IO.mapOptional("AcrossEmptyLines", Value.AcrossEmptyLines);95 IO.mapOptional("AcrossComments", Value.AcrossComments);96 IO.mapOptional("AlignCompound", Value.AlignCompound);97 IO.mapOptional("AlignFunctionDeclarations",98 Value.AlignFunctionDeclarations);99 IO.mapOptional("AlignFunctionPointers", Value.AlignFunctionPointers);100 IO.mapOptional("PadOperators", Value.PadOperators);101 }102};103 104template <>105struct MappingTraits<FormatStyle::ShortCaseStatementsAlignmentStyle> {106 static void mapping(IO &IO,107 FormatStyle::ShortCaseStatementsAlignmentStyle &Value) {108 IO.mapOptional("Enabled", Value.Enabled);109 IO.mapOptional("AcrossEmptyLines", Value.AcrossEmptyLines);110 IO.mapOptional("AcrossComments", Value.AcrossComments);111 IO.mapOptional("AlignCaseArrows", Value.AlignCaseArrows);112 IO.mapOptional("AlignCaseColons", Value.AlignCaseColons);113 }114};115 116template <>117struct ScalarEnumerationTraits<FormatStyle::AttributeBreakingStyle> {118 static void enumeration(IO &IO, FormatStyle::AttributeBreakingStyle &Value) {119 IO.enumCase(Value, "Always", FormatStyle::ABS_Always);120 IO.enumCase(Value, "Leave", FormatStyle::ABS_Leave);121 IO.enumCase(Value, "Never", FormatStyle::ABS_Never);122 }123};124 125template <>126struct ScalarEnumerationTraits<FormatStyle::ArrayInitializerAlignmentStyle> {127 static void enumeration(IO &IO,128 FormatStyle::ArrayInitializerAlignmentStyle &Value) {129 IO.enumCase(Value, "None", FormatStyle::AIAS_None);130 IO.enumCase(Value, "Left", FormatStyle::AIAS_Left);131 IO.enumCase(Value, "Right", FormatStyle::AIAS_Right);132 }133};134 135template <> struct ScalarEnumerationTraits<FormatStyle::BinaryOperatorStyle> {136 static void enumeration(IO &IO, FormatStyle::BinaryOperatorStyle &Value) {137 IO.enumCase(Value, "All", FormatStyle::BOS_All);138 IO.enumCase(Value, "true", FormatStyle::BOS_All);139 IO.enumCase(Value, "None", FormatStyle::BOS_None);140 IO.enumCase(Value, "false", FormatStyle::BOS_None);141 IO.enumCase(Value, "NonAssignment", FormatStyle::BOS_NonAssignment);142 }143};144 145template <>146struct ScalarEnumerationTraits<FormatStyle::BinPackParametersStyle> {147 static void enumeration(IO &IO, FormatStyle::BinPackParametersStyle &Value) {148 IO.enumCase(Value, "BinPack", FormatStyle::BPPS_BinPack);149 IO.enumCase(Value, "OnePerLine", FormatStyle::BPPS_OnePerLine);150 IO.enumCase(Value, "AlwaysOnePerLine", FormatStyle::BPPS_AlwaysOnePerLine);151 152 // For backward compatibility.153 IO.enumCase(Value, "true", FormatStyle::BPPS_BinPack);154 IO.enumCase(Value, "false", FormatStyle::BPPS_OnePerLine);155 }156};157 158template <> struct ScalarEnumerationTraits<FormatStyle::BinPackStyle> {159 static void enumeration(IO &IO, FormatStyle::BinPackStyle &Value) {160 IO.enumCase(Value, "Auto", FormatStyle::BPS_Auto);161 IO.enumCase(Value, "Always", FormatStyle::BPS_Always);162 IO.enumCase(Value, "Never", FormatStyle::BPS_Never);163 }164};165 166template <>167struct ScalarEnumerationTraits<FormatStyle::BitFieldColonSpacingStyle> {168 static void enumeration(IO &IO,169 FormatStyle::BitFieldColonSpacingStyle &Value) {170 IO.enumCase(Value, "Both", FormatStyle::BFCS_Both);171 IO.enumCase(Value, "None", FormatStyle::BFCS_None);172 IO.enumCase(Value, "Before", FormatStyle::BFCS_Before);173 IO.enumCase(Value, "After", FormatStyle::BFCS_After);174 }175};176 177template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> {178 static void enumeration(IO &IO, FormatStyle::BraceBreakingStyle &Value) {179 IO.enumCase(Value, "Attach", FormatStyle::BS_Attach);180 IO.enumCase(Value, "Linux", FormatStyle::BS_Linux);181 IO.enumCase(Value, "Mozilla", FormatStyle::BS_Mozilla);182 IO.enumCase(Value, "Stroustrup", FormatStyle::BS_Stroustrup);183 IO.enumCase(Value, "Allman", FormatStyle::BS_Allman);184 IO.enumCase(Value, "Whitesmiths", FormatStyle::BS_Whitesmiths);185 IO.enumCase(Value, "GNU", FormatStyle::BS_GNU);186 IO.enumCase(Value, "WebKit", FormatStyle::BS_WebKit);187 IO.enumCase(Value, "Custom", FormatStyle::BS_Custom);188 }189};190 191template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> {192 static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping) {193 IO.mapOptional("AfterCaseLabel", Wrapping.AfterCaseLabel);194 IO.mapOptional("AfterClass", Wrapping.AfterClass);195 IO.mapOptional("AfterControlStatement", Wrapping.AfterControlStatement);196 IO.mapOptional("AfterEnum", Wrapping.AfterEnum);197 IO.mapOptional("AfterExternBlock", Wrapping.AfterExternBlock);198 IO.mapOptional("AfterFunction", Wrapping.AfterFunction);199 IO.mapOptional("AfterNamespace", Wrapping.AfterNamespace);200 IO.mapOptional("AfterObjCDeclaration", Wrapping.AfterObjCDeclaration);201 IO.mapOptional("AfterStruct", Wrapping.AfterStruct);202 IO.mapOptional("AfterUnion", Wrapping.AfterUnion);203 IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch);204 IO.mapOptional("BeforeElse", Wrapping.BeforeElse);205 IO.mapOptional("BeforeLambdaBody", Wrapping.BeforeLambdaBody);206 IO.mapOptional("BeforeWhile", Wrapping.BeforeWhile);207 IO.mapOptional("IndentBraces", Wrapping.IndentBraces);208 IO.mapOptional("SplitEmptyFunction", Wrapping.SplitEmptyFunction);209 IO.mapOptional("SplitEmptyRecord", Wrapping.SplitEmptyRecord);210 IO.mapOptional("SplitEmptyNamespace", Wrapping.SplitEmptyNamespace);211 }212};213 214template <> struct ScalarEnumerationTraits<BracketAlignmentStyle> {215 static void enumeration(IO &IO, BracketAlignmentStyle &Value) {216 IO.enumCase(Value, "Align", BAS_Align);217 IO.enumCase(Value, "DontAlign", BAS_DontAlign);218 219 // For backward compatibility.220 IO.enumCase(Value, "true", BAS_Align);221 IO.enumCase(Value, "false", BAS_DontAlign);222 IO.enumCase(Value, "AlwaysBreak", BAS_AlwaysBreak);223 IO.enumCase(Value, "BlockIndent", BAS_BlockIndent);224 }225};226 227template <>228struct ScalarEnumerationTraits<229 FormatStyle::BraceWrappingAfterControlStatementStyle> {230 static void231 enumeration(IO &IO,232 FormatStyle::BraceWrappingAfterControlStatementStyle &Value) {233 IO.enumCase(Value, "Never", FormatStyle::BWACS_Never);234 IO.enumCase(Value, "MultiLine", FormatStyle::BWACS_MultiLine);235 IO.enumCase(Value, "Always", FormatStyle::BWACS_Always);236 237 // For backward compatibility.238 IO.enumCase(Value, "false", FormatStyle::BWACS_Never);239 IO.enumCase(Value, "true", FormatStyle::BWACS_Always);240 }241};242 243template <>244struct ScalarEnumerationTraits<245 FormatStyle::BreakBeforeConceptDeclarationsStyle> {246 static void247 enumeration(IO &IO, FormatStyle::BreakBeforeConceptDeclarationsStyle &Value) {248 IO.enumCase(Value, "Never", FormatStyle::BBCDS_Never);249 IO.enumCase(Value, "Allowed", FormatStyle::BBCDS_Allowed);250 IO.enumCase(Value, "Always", FormatStyle::BBCDS_Always);251 252 // For backward compatibility.253 IO.enumCase(Value, "true", FormatStyle::BBCDS_Always);254 IO.enumCase(Value, "false", FormatStyle::BBCDS_Allowed);255 }256};257 258template <>259struct ScalarEnumerationTraits<FormatStyle::BreakBeforeInlineASMColonStyle> {260 static void enumeration(IO &IO,261 FormatStyle::BreakBeforeInlineASMColonStyle &Value) {262 IO.enumCase(Value, "Never", FormatStyle::BBIAS_Never);263 IO.enumCase(Value, "OnlyMultiline", FormatStyle::BBIAS_OnlyMultiline);264 IO.enumCase(Value, "Always", FormatStyle::BBIAS_Always);265 }266};267 268template <>269struct ScalarEnumerationTraits<FormatStyle::BreakBinaryOperationsStyle> {270 static void enumeration(IO &IO,271 FormatStyle::BreakBinaryOperationsStyle &Value) {272 IO.enumCase(Value, "Never", FormatStyle::BBO_Never);273 IO.enumCase(Value, "OnePerLine", FormatStyle::BBO_OnePerLine);274 IO.enumCase(Value, "RespectPrecedence", FormatStyle::BBO_RespectPrecedence);275 }276};277 278template <>279struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> {280 static void281 enumeration(IO &IO, FormatStyle::BreakConstructorInitializersStyle &Value) {282 IO.enumCase(Value, "BeforeColon", FormatStyle::BCIS_BeforeColon);283 IO.enumCase(Value, "BeforeComma", FormatStyle::BCIS_BeforeComma);284 IO.enumCase(Value, "AfterColon", FormatStyle::BCIS_AfterColon);285 }286};287 288template <>289struct ScalarEnumerationTraits<FormatStyle::BreakInheritanceListStyle> {290 static void enumeration(IO &IO,291 FormatStyle::BreakInheritanceListStyle &Value) {292 IO.enumCase(Value, "BeforeColon", FormatStyle::BILS_BeforeColon);293 IO.enumCase(Value, "BeforeComma", FormatStyle::BILS_BeforeComma);294 IO.enumCase(Value, "AfterColon", FormatStyle::BILS_AfterColon);295 IO.enumCase(Value, "AfterComma", FormatStyle::BILS_AfterComma);296 }297};298 299template <>300struct ScalarEnumerationTraits<FormatStyle::BreakTemplateDeclarationsStyle> {301 static void enumeration(IO &IO,302 FormatStyle::BreakTemplateDeclarationsStyle &Value) {303 IO.enumCase(Value, "Leave", FormatStyle::BTDS_Leave);304 IO.enumCase(Value, "No", FormatStyle::BTDS_No);305 IO.enumCase(Value, "MultiLine", FormatStyle::BTDS_MultiLine);306 IO.enumCase(Value, "Yes", FormatStyle::BTDS_Yes);307 308 // For backward compatibility.309 IO.enumCase(Value, "false", FormatStyle::BTDS_MultiLine);310 IO.enumCase(Value, "true", FormatStyle::BTDS_Yes);311 }312};313 314template <> struct ScalarEnumerationTraits<FormatStyle::BracedListStyle> {315 static void enumeration(IO &IO, FormatStyle::BracedListStyle &Value) {316 IO.enumCase(Value, "Block", FormatStyle::BLS_Block);317 IO.enumCase(Value, "FunctionCall", FormatStyle::BLS_FunctionCall);318 IO.enumCase(Value, "AlignFirstComment", FormatStyle::BLS_AlignFirstComment);319 320 // For backward compatibility.321 IO.enumCase(Value, "false", FormatStyle::BLS_Block);322 IO.enumCase(Value, "true", FormatStyle::BLS_AlignFirstComment);323 }324};325 326template <> struct ScalarEnumerationTraits<FormatStyle::DAGArgStyle> {327 static void enumeration(IO &IO, FormatStyle::DAGArgStyle &Value) {328 IO.enumCase(Value, "DontBreak", FormatStyle::DAS_DontBreak);329 IO.enumCase(Value, "BreakElements", FormatStyle::DAS_BreakElements);330 IO.enumCase(Value, "BreakAll", FormatStyle::DAS_BreakAll);331 }332};333 334template <>335struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> {336 static void337 enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) {338 IO.enumCase(Value, "None", FormatStyle::DRTBS_None);339 IO.enumCase(Value, "All", FormatStyle::DRTBS_All);340 IO.enumCase(Value, "TopLevel", FormatStyle::DRTBS_TopLevel);341 342 // For backward compatibility.343 IO.enumCase(Value, "false", FormatStyle::DRTBS_None);344 IO.enumCase(Value, "true", FormatStyle::DRTBS_All);345 }346};347 348template <>349struct ScalarEnumerationTraits<FormatStyle::EscapedNewlineAlignmentStyle> {350 static void enumeration(IO &IO,351 FormatStyle::EscapedNewlineAlignmentStyle &Value) {352 IO.enumCase(Value, "DontAlign", FormatStyle::ENAS_DontAlign);353 IO.enumCase(Value, "Left", FormatStyle::ENAS_Left);354 IO.enumCase(Value, "LeftWithLastLine", FormatStyle::ENAS_LeftWithLastLine);355 IO.enumCase(Value, "Right", FormatStyle::ENAS_Right);356 357 // For backward compatibility.358 IO.enumCase(Value, "true", FormatStyle::ENAS_Left);359 IO.enumCase(Value, "false", FormatStyle::ENAS_Right);360 }361};362 363template <>364struct ScalarEnumerationTraits<FormatStyle::EmptyLineAfterAccessModifierStyle> {365 static void366 enumeration(IO &IO, FormatStyle::EmptyLineAfterAccessModifierStyle &Value) {367 IO.enumCase(Value, "Never", FormatStyle::ELAAMS_Never);368 IO.enumCase(Value, "Leave", FormatStyle::ELAAMS_Leave);369 IO.enumCase(Value, "Always", FormatStyle::ELAAMS_Always);370 }371};372 373template <>374struct ScalarEnumerationTraits<375 FormatStyle::EmptyLineBeforeAccessModifierStyle> {376 static void377 enumeration(IO &IO, FormatStyle::EmptyLineBeforeAccessModifierStyle &Value) {378 IO.enumCase(Value, "Never", FormatStyle::ELBAMS_Never);379 IO.enumCase(Value, "Leave", FormatStyle::ELBAMS_Leave);380 IO.enumCase(Value, "LogicalBlock", FormatStyle::ELBAMS_LogicalBlock);381 IO.enumCase(Value, "Always", FormatStyle::ELBAMS_Always);382 }383};384 385template <>386struct ScalarEnumerationTraits<FormatStyle::EnumTrailingCommaStyle> {387 static void enumeration(IO &IO, FormatStyle::EnumTrailingCommaStyle &Value) {388 IO.enumCase(Value, "Leave", FormatStyle::ETC_Leave);389 IO.enumCase(Value, "Insert", FormatStyle::ETC_Insert);390 IO.enumCase(Value, "Remove", FormatStyle::ETC_Remove);391 }392};393 394template <>395struct ScalarEnumerationTraits<FormatStyle::IndentExternBlockStyle> {396 static void enumeration(IO &IO, FormatStyle::IndentExternBlockStyle &Value) {397 IO.enumCase(Value, "AfterExternBlock", FormatStyle::IEBS_AfterExternBlock);398 IO.enumCase(Value, "Indent", FormatStyle::IEBS_Indent);399 IO.enumCase(Value, "NoIndent", FormatStyle::IEBS_NoIndent);400 IO.enumCase(Value, "true", FormatStyle::IEBS_Indent);401 IO.enumCase(Value, "false", FormatStyle::IEBS_NoIndent);402 }403};404 405template <> struct MappingTraits<FormatStyle::IntegerLiteralSeparatorStyle> {406 static void mapping(IO &IO, FormatStyle::IntegerLiteralSeparatorStyle &Base) {407 IO.mapOptional("Binary", Base.Binary);408 IO.mapOptional("BinaryMinDigitsInsert", Base.BinaryMinDigitsInsert);409 IO.mapOptional("BinaryMaxDigitsRemove", Base.BinaryMaxDigitsRemove);410 IO.mapOptional("Decimal", Base.Decimal);411 IO.mapOptional("DecimalMinDigitsInsert", Base.DecimalMinDigitsInsert);412 IO.mapOptional("DecimalMaxDigitsRemove", Base.DecimalMaxDigitsRemove);413 IO.mapOptional("Hex", Base.Hex);414 IO.mapOptional("HexMinDigitsInsert", Base.HexMinDigitsInsert);415 IO.mapOptional("HexMaxDigitsRemove", Base.HexMaxDigitsRemove);416 417 // For backward compatibility.418 IO.mapOptional("BinaryMinDigits", Base.BinaryMinDigitsInsert);419 IO.mapOptional("DecimalMinDigits", Base.DecimalMinDigitsInsert);420 IO.mapOptional("HexMinDigits", Base.HexMinDigitsInsert);421 }422};423 424template <> struct ScalarEnumerationTraits<FormatStyle::JavaScriptQuoteStyle> {425 static void enumeration(IO &IO, FormatStyle::JavaScriptQuoteStyle &Value) {426 IO.enumCase(Value, "Leave", FormatStyle::JSQS_Leave);427 IO.enumCase(Value, "Single", FormatStyle::JSQS_Single);428 IO.enumCase(Value, "Double", FormatStyle::JSQS_Double);429 }430};431 432template <> struct MappingTraits<FormatStyle::KeepEmptyLinesStyle> {433 static void mapping(IO &IO, FormatStyle::KeepEmptyLinesStyle &Value) {434 IO.mapOptional("AtEndOfFile", Value.AtEndOfFile);435 IO.mapOptional("AtStartOfBlock", Value.AtStartOfBlock);436 IO.mapOptional("AtStartOfFile", Value.AtStartOfFile);437 }438};439 440template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> {441 static void enumeration(IO &IO, FormatStyle::LanguageKind &Value) {442 IO.enumCase(Value, "C", FormatStyle::LK_C);443 IO.enumCase(Value, "Cpp", FormatStyle::LK_Cpp);444 IO.enumCase(Value, "Java", FormatStyle::LK_Java);445 IO.enumCase(Value, "JavaScript", FormatStyle::LK_JavaScript);446 IO.enumCase(Value, "ObjC", FormatStyle::LK_ObjC);447 IO.enumCase(Value, "Proto", FormatStyle::LK_Proto);448 IO.enumCase(Value, "TableGen", FormatStyle::LK_TableGen);449 IO.enumCase(Value, "TextProto", FormatStyle::LK_TextProto);450 IO.enumCase(Value, "CSharp", FormatStyle::LK_CSharp);451 IO.enumCase(Value, "Json", FormatStyle::LK_Json);452 IO.enumCase(Value, "Verilog", FormatStyle::LK_Verilog);453 }454};455 456template <> struct ScalarEnumerationTraits<FormatStyle::LanguageStandard> {457 static void enumeration(IO &IO, FormatStyle::LanguageStandard &Value) {458 IO.enumCase(Value, "c++03", FormatStyle::LS_Cpp03);459 IO.enumCase(Value, "C++03", FormatStyle::LS_Cpp03); // Legacy alias460 IO.enumCase(Value, "Cpp03", FormatStyle::LS_Cpp03); // Legacy alias461 462 IO.enumCase(Value, "c++11", FormatStyle::LS_Cpp11);463 IO.enumCase(Value, "C++11", FormatStyle::LS_Cpp11); // Legacy alias464 465 IO.enumCase(Value, "c++14", FormatStyle::LS_Cpp14);466 IO.enumCase(Value, "c++17", FormatStyle::LS_Cpp17);467 IO.enumCase(Value, "c++20", FormatStyle::LS_Cpp20);468 469 IO.enumCase(Value, "Latest", FormatStyle::LS_Latest);470 IO.enumCase(Value, "Cpp11", FormatStyle::LS_Latest); // Legacy alias471 IO.enumCase(Value, "Auto", FormatStyle::LS_Auto);472 }473};474 475template <>476struct ScalarEnumerationTraits<FormatStyle::LambdaBodyIndentationKind> {477 static void enumeration(IO &IO,478 FormatStyle::LambdaBodyIndentationKind &Value) {479 IO.enumCase(Value, "Signature", FormatStyle::LBI_Signature);480 IO.enumCase(Value, "OuterScope", FormatStyle::LBI_OuterScope);481 }482};483 484template <> struct ScalarEnumerationTraits<FormatStyle::LineEndingStyle> {485 static void enumeration(IO &IO, FormatStyle::LineEndingStyle &Value) {486 IO.enumCase(Value, "LF", FormatStyle::LE_LF);487 IO.enumCase(Value, "CRLF", FormatStyle::LE_CRLF);488 IO.enumCase(Value, "DeriveLF", FormatStyle::LE_DeriveLF);489 IO.enumCase(Value, "DeriveCRLF", FormatStyle::LE_DeriveCRLF);490 }491};492 493template <>494struct ScalarEnumerationTraits<FormatStyle::NamespaceIndentationKind> {495 static void enumeration(IO &IO,496 FormatStyle::NamespaceIndentationKind &Value) {497 IO.enumCase(Value, "None", FormatStyle::NI_None);498 IO.enumCase(Value, "Inner", FormatStyle::NI_Inner);499 IO.enumCase(Value, "All", FormatStyle::NI_All);500 }501};502 503template <>504struct ScalarEnumerationTraits<FormatStyle::NumericLiteralComponentStyle> {505 static void enumeration(IO &IO,506 FormatStyle::NumericLiteralComponentStyle &Value) {507 IO.enumCase(Value, "Leave", FormatStyle::NLCS_Leave);508 IO.enumCase(Value, "Upper", FormatStyle::NLCS_Upper);509 IO.enumCase(Value, "Lower", FormatStyle::NLCS_Lower);510 }511};512 513template <> struct MappingTraits<FormatStyle::NumericLiteralCaseStyle> {514 static void mapping(IO &IO, FormatStyle::NumericLiteralCaseStyle &Value) {515 IO.mapOptional("ExponentLetter", Value.ExponentLetter);516 IO.mapOptional("HexDigit", Value.HexDigit);517 IO.mapOptional("Prefix", Value.Prefix);518 IO.mapOptional("Suffix", Value.Suffix);519 }520};521 522template <> struct ScalarEnumerationTraits<FormatStyle::OperandAlignmentStyle> {523 static void enumeration(IO &IO, FormatStyle::OperandAlignmentStyle &Value) {524 IO.enumCase(Value, "DontAlign", FormatStyle::OAS_DontAlign);525 IO.enumCase(Value, "Align", FormatStyle::OAS_Align);526 IO.enumCase(Value, "AlignAfterOperator",527 FormatStyle::OAS_AlignAfterOperator);528 529 // For backward compatibility.530 IO.enumCase(Value, "true", FormatStyle::OAS_Align);531 IO.enumCase(Value, "false", FormatStyle::OAS_DontAlign);532 }533};534 535template <>536struct ScalarEnumerationTraits<FormatStyle::PackConstructorInitializersStyle> {537 static void538 enumeration(IO &IO, FormatStyle::PackConstructorInitializersStyle &Value) {539 IO.enumCase(Value, "Never", FormatStyle::PCIS_Never);540 IO.enumCase(Value, "BinPack", FormatStyle::PCIS_BinPack);541 IO.enumCase(Value, "CurrentLine", FormatStyle::PCIS_CurrentLine);542 IO.enumCase(Value, "NextLine", FormatStyle::PCIS_NextLine);543 IO.enumCase(Value, "NextLineOnly", FormatStyle::PCIS_NextLineOnly);544 }545};546 547template <> struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {548 static void enumeration(IO &IO, FormatStyle::PointerAlignmentStyle &Value) {549 IO.enumCase(Value, "Middle", FormatStyle::PAS_Middle);550 IO.enumCase(Value, "Left", FormatStyle::PAS_Left);551 IO.enumCase(Value, "Right", FormatStyle::PAS_Right);552 553 // For backward compatibility.554 IO.enumCase(Value, "true", FormatStyle::PAS_Left);555 IO.enumCase(Value, "false", FormatStyle::PAS_Right);556 }557};558 559template <>560struct ScalarEnumerationTraits<FormatStyle::PPDirectiveIndentStyle> {561 static void enumeration(IO &IO, FormatStyle::PPDirectiveIndentStyle &Value) {562 IO.enumCase(Value, "None", FormatStyle::PPDIS_None);563 IO.enumCase(Value, "AfterHash", FormatStyle::PPDIS_AfterHash);564 IO.enumCase(Value, "BeforeHash", FormatStyle::PPDIS_BeforeHash);565 IO.enumCase(Value, "Leave", FormatStyle::PPDIS_Leave);566 }567};568 569template <>570struct ScalarEnumerationTraits<FormatStyle::QualifierAlignmentStyle> {571 static void enumeration(IO &IO, FormatStyle::QualifierAlignmentStyle &Value) {572 IO.enumCase(Value, "Leave", FormatStyle::QAS_Leave);573 IO.enumCase(Value, "Left", FormatStyle::QAS_Left);574 IO.enumCase(Value, "Right", FormatStyle::QAS_Right);575 IO.enumCase(Value, "Custom", FormatStyle::QAS_Custom);576 }577};578 579template <> struct MappingTraits<FormatStyle::RawStringFormat> {580 static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) {581 IO.mapOptional("Language", Format.Language);582 IO.mapOptional("Delimiters", Format.Delimiters);583 IO.mapOptional("EnclosingFunctions", Format.EnclosingFunctions);584 IO.mapOptional("CanonicalDelimiter", Format.CanonicalDelimiter);585 IO.mapOptional("BasedOnStyle", Format.BasedOnStyle);586 }587};588 589template <> struct ScalarEnumerationTraits<FormatStyle::ReflowCommentsStyle> {590 static void enumeration(IO &IO, FormatStyle::ReflowCommentsStyle &Value) {591 IO.enumCase(Value, "Never", FormatStyle::RCS_Never);592 IO.enumCase(Value, "IndentOnly", FormatStyle::RCS_IndentOnly);593 IO.enumCase(Value, "Always", FormatStyle::RCS_Always);594 // For backward compatibility:595 IO.enumCase(Value, "false", FormatStyle::RCS_Never);596 IO.enumCase(Value, "true", FormatStyle::RCS_Always);597 }598};599 600template <>601struct ScalarEnumerationTraits<FormatStyle::ReferenceAlignmentStyle> {602 static void enumeration(IO &IO, FormatStyle::ReferenceAlignmentStyle &Value) {603 IO.enumCase(Value, "Pointer", FormatStyle::RAS_Pointer);604 IO.enumCase(Value, "Middle", FormatStyle::RAS_Middle);605 IO.enumCase(Value, "Left", FormatStyle::RAS_Left);606 IO.enumCase(Value, "Right", FormatStyle::RAS_Right);607 }608};609 610template <>611struct ScalarEnumerationTraits<FormatStyle::RemoveParenthesesStyle> {612 static void enumeration(IO &IO, FormatStyle::RemoveParenthesesStyle &Value) {613 IO.enumCase(Value, "Leave", FormatStyle::RPS_Leave);614 IO.enumCase(Value, "MultipleParentheses",615 FormatStyle::RPS_MultipleParentheses);616 IO.enumCase(Value, "ReturnStatement", FormatStyle::RPS_ReturnStatement);617 }618};619 620template <>621struct ScalarEnumerationTraits<FormatStyle::RequiresClausePositionStyle> {622 static void enumeration(IO &IO,623 FormatStyle::RequiresClausePositionStyle &Value) {624 IO.enumCase(Value, "OwnLine", FormatStyle::RCPS_OwnLine);625 IO.enumCase(Value, "OwnLineWithBrace", FormatStyle::RCPS_OwnLineWithBrace);626 IO.enumCase(Value, "WithPreceding", FormatStyle::RCPS_WithPreceding);627 IO.enumCase(Value, "WithFollowing", FormatStyle::RCPS_WithFollowing);628 IO.enumCase(Value, "SingleLine", FormatStyle::RCPS_SingleLine);629 }630};631 632template <>633struct ScalarEnumerationTraits<FormatStyle::RequiresExpressionIndentationKind> {634 static void635 enumeration(IO &IO, FormatStyle::RequiresExpressionIndentationKind &Value) {636 IO.enumCase(Value, "Keyword", FormatStyle::REI_Keyword);637 IO.enumCase(Value, "OuterScope", FormatStyle::REI_OuterScope);638 }639};640 641template <>642struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> {643 static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) {644 IO.enumCase(Value, "None", FormatStyle::RTBS_None);645 IO.enumCase(Value, "Automatic", FormatStyle::RTBS_Automatic);646 IO.enumCase(Value, "ExceptShortType", FormatStyle::RTBS_ExceptShortType);647 IO.enumCase(Value, "All", FormatStyle::RTBS_All);648 IO.enumCase(Value, "TopLevel", FormatStyle::RTBS_TopLevel);649 IO.enumCase(Value, "TopLevelDefinitions",650 FormatStyle::RTBS_TopLevelDefinitions);651 IO.enumCase(Value, "AllDefinitions", FormatStyle::RTBS_AllDefinitions);652 }653};654 655template <>656struct ScalarEnumerationTraits<FormatStyle::SeparateDefinitionStyle> {657 static void enumeration(IO &IO, FormatStyle::SeparateDefinitionStyle &Value) {658 IO.enumCase(Value, "Leave", FormatStyle::SDS_Leave);659 IO.enumCase(Value, "Always", FormatStyle::SDS_Always);660 IO.enumCase(Value, "Never", FormatStyle::SDS_Never);661 }662};663 664template <> struct ScalarEnumerationTraits<FormatStyle::ShortBlockStyle> {665 static void enumeration(IO &IO, FormatStyle::ShortBlockStyle &Value) {666 IO.enumCase(Value, "Never", FormatStyle::SBS_Never);667 IO.enumCase(Value, "false", FormatStyle::SBS_Never);668 IO.enumCase(Value, "Always", FormatStyle::SBS_Always);669 IO.enumCase(Value, "true", FormatStyle::SBS_Always);670 IO.enumCase(Value, "Empty", FormatStyle::SBS_Empty);671 }672};673 674template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> {675 static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) {676 IO.enumCase(Value, "None", FormatStyle::SFS_None);677 IO.enumCase(Value, "false", FormatStyle::SFS_None);678 IO.enumCase(Value, "All", FormatStyle::SFS_All);679 IO.enumCase(Value, "true", FormatStyle::SFS_All);680 IO.enumCase(Value, "Inline", FormatStyle::SFS_Inline);681 IO.enumCase(Value, "InlineOnly", FormatStyle::SFS_InlineOnly);682 IO.enumCase(Value, "Empty", FormatStyle::SFS_Empty);683 }684};685 686template <> struct ScalarEnumerationTraits<FormatStyle::ShortIfStyle> {687 static void enumeration(IO &IO, FormatStyle::ShortIfStyle &Value) {688 IO.enumCase(Value, "Never", FormatStyle::SIS_Never);689 IO.enumCase(Value, "WithoutElse", FormatStyle::SIS_WithoutElse);690 IO.enumCase(Value, "OnlyFirstIf", FormatStyle::SIS_OnlyFirstIf);691 IO.enumCase(Value, "AllIfsAndElse", FormatStyle::SIS_AllIfsAndElse);692 693 // For backward compatibility.694 IO.enumCase(Value, "Always", FormatStyle::SIS_OnlyFirstIf);695 IO.enumCase(Value, "false", FormatStyle::SIS_Never);696 IO.enumCase(Value, "true", FormatStyle::SIS_WithoutElse);697 }698};699 700template <> struct ScalarEnumerationTraits<FormatStyle::ShortLambdaStyle> {701 static void enumeration(IO &IO, FormatStyle::ShortLambdaStyle &Value) {702 IO.enumCase(Value, "None", FormatStyle::SLS_None);703 IO.enumCase(Value, "false", FormatStyle::SLS_None);704 IO.enumCase(Value, "Empty", FormatStyle::SLS_Empty);705 IO.enumCase(Value, "Inline", FormatStyle::SLS_Inline);706 IO.enumCase(Value, "All", FormatStyle::SLS_All);707 IO.enumCase(Value, "true", FormatStyle::SLS_All);708 }709};710 711template <> struct MappingTraits<FormatStyle::SortIncludesOptions> {712 static void enumInput(IO &IO, FormatStyle::SortIncludesOptions &Value) {713 IO.enumCase(Value, "Never", FormatStyle::SortIncludesOptions({}));714 IO.enumCase(Value, "CaseInsensitive",715 FormatStyle::SortIncludesOptions({/*Enabled=*/true,716 /*IgnoreCase=*/true,717 /*IgnoreExtension=*/false}));718 IO.enumCase(Value, "CaseSensitive",719 FormatStyle::SortIncludesOptions({/*Enabled=*/true,720 /*IgnoreCase=*/false,721 /*IgnoreExtension=*/false}));722 723 // For backward compatibility.724 IO.enumCase(Value, "false", FormatStyle::SortIncludesOptions({}));725 IO.enumCase(Value, "true",726 FormatStyle::SortIncludesOptions({/*Enabled=*/true,727 /*IgnoreCase=*/false,728 /*IgnoreExtension=*/false}));729 }730 731 static void mapping(IO &IO, FormatStyle::SortIncludesOptions &Value) {732 IO.mapOptional("Enabled", Value.Enabled);733 IO.mapOptional("IgnoreCase", Value.IgnoreCase);734 IO.mapOptional("IgnoreExtension", Value.IgnoreExtension);735 }736};737 738template <>739struct ScalarEnumerationTraits<FormatStyle::SortJavaStaticImportOptions> {740 static void enumeration(IO &IO,741 FormatStyle::SortJavaStaticImportOptions &Value) {742 IO.enumCase(Value, "Before", FormatStyle::SJSIO_Before);743 IO.enumCase(Value, "After", FormatStyle::SJSIO_After);744 }745};746 747template <>748struct ScalarEnumerationTraits<FormatStyle::SortUsingDeclarationsOptions> {749 static void enumeration(IO &IO,750 FormatStyle::SortUsingDeclarationsOptions &Value) {751 IO.enumCase(Value, "Never", FormatStyle::SUD_Never);752 IO.enumCase(Value, "Lexicographic", FormatStyle::SUD_Lexicographic);753 IO.enumCase(Value, "LexicographicNumeric",754 FormatStyle::SUD_LexicographicNumeric);755 756 // For backward compatibility.757 IO.enumCase(Value, "false", FormatStyle::SUD_Never);758 IO.enumCase(Value, "true", FormatStyle::SUD_LexicographicNumeric);759 }760};761 762template <>763struct ScalarEnumerationTraits<FormatStyle::SpaceAroundPointerQualifiersStyle> {764 static void765 enumeration(IO &IO, FormatStyle::SpaceAroundPointerQualifiersStyle &Value) {766 IO.enumCase(Value, "Default", FormatStyle::SAPQ_Default);767 IO.enumCase(Value, "Before", FormatStyle::SAPQ_Before);768 IO.enumCase(Value, "After", FormatStyle::SAPQ_After);769 IO.enumCase(Value, "Both", FormatStyle::SAPQ_Both);770 }771};772 773template <> struct MappingTraits<FormatStyle::SpaceBeforeParensCustom> {774 static void mapping(IO &IO, FormatStyle::SpaceBeforeParensCustom &Spacing) {775 IO.mapOptional("AfterControlStatements", Spacing.AfterControlStatements);776 IO.mapOptional("AfterForeachMacros", Spacing.AfterForeachMacros);777 IO.mapOptional("AfterFunctionDefinitionName",778 Spacing.AfterFunctionDefinitionName);779 IO.mapOptional("AfterFunctionDeclarationName",780 Spacing.AfterFunctionDeclarationName);781 IO.mapOptional("AfterIfMacros", Spacing.AfterIfMacros);782 IO.mapOptional("AfterNot", Spacing.AfterNot);783 IO.mapOptional("AfterOverloadedOperator", Spacing.AfterOverloadedOperator);784 IO.mapOptional("AfterPlacementOperator", Spacing.AfterPlacementOperator);785 IO.mapOptional("AfterRequiresInClause", Spacing.AfterRequiresInClause);786 IO.mapOptional("AfterRequiresInExpression",787 Spacing.AfterRequiresInExpression);788 IO.mapOptional("BeforeNonEmptyParentheses",789 Spacing.BeforeNonEmptyParentheses);790 }791};792 793template <>794struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensStyle> {795 static void enumeration(IO &IO, FormatStyle::SpaceBeforeParensStyle &Value) {796 IO.enumCase(Value, "Never", FormatStyle::SBPO_Never);797 IO.enumCase(Value, "ControlStatements",798 FormatStyle::SBPO_ControlStatements);799 IO.enumCase(Value, "ControlStatementsExceptControlMacros",800 FormatStyle::SBPO_ControlStatementsExceptControlMacros);801 IO.enumCase(Value, "NonEmptyParentheses",802 FormatStyle::SBPO_NonEmptyParentheses);803 IO.enumCase(Value, "Always", FormatStyle::SBPO_Always);804 IO.enumCase(Value, "Custom", FormatStyle::SBPO_Custom);805 806 // For backward compatibility.807 IO.enumCase(Value, "false", FormatStyle::SBPO_Never);808 IO.enumCase(Value, "true", FormatStyle::SBPO_ControlStatements);809 IO.enumCase(Value, "ControlStatementsExceptForEachMacros",810 FormatStyle::SBPO_ControlStatementsExceptControlMacros);811 }812};813 814template <>815struct ScalarEnumerationTraits<FormatStyle::SpaceInEmptyBracesStyle> {816 static void enumeration(IO &IO, FormatStyle::SpaceInEmptyBracesStyle &Value) {817 IO.enumCase(Value, "Always", FormatStyle::SIEB_Always);818 IO.enumCase(Value, "Block", FormatStyle::SIEB_Block);819 IO.enumCase(Value, "Never", FormatStyle::SIEB_Never);820 }821};822 823template <> struct ScalarEnumerationTraits<FormatStyle::SpacesInAnglesStyle> {824 static void enumeration(IO &IO, FormatStyle::SpacesInAnglesStyle &Value) {825 IO.enumCase(Value, "Never", FormatStyle::SIAS_Never);826 IO.enumCase(Value, "Always", FormatStyle::SIAS_Always);827 IO.enumCase(Value, "Leave", FormatStyle::SIAS_Leave);828 829 // For backward compatibility.830 IO.enumCase(Value, "false", FormatStyle::SIAS_Never);831 IO.enumCase(Value, "true", FormatStyle::SIAS_Always);832 }833};834 835template <> struct MappingTraits<FormatStyle::SpacesInLineComment> {836 static void mapping(IO &IO, FormatStyle::SpacesInLineComment &Space) {837 // Transform the maximum to signed, to parse "-1" correctly838 int signedMaximum = static_cast<int>(Space.Maximum);839 IO.mapOptional("Minimum", Space.Minimum);840 IO.mapOptional("Maximum", signedMaximum);841 Space.Maximum = static_cast<unsigned>(signedMaximum);842 843 if (Space.Maximum < std::numeric_limits<unsigned>::max())844 Space.Minimum = std::min(Space.Minimum, Space.Maximum);845 }846};847 848template <> struct MappingTraits<FormatStyle::SpacesInParensCustom> {849 static void mapping(IO &IO, FormatStyle::SpacesInParensCustom &Spaces) {850 IO.mapOptional("ExceptDoubleParentheses", Spaces.ExceptDoubleParentheses);851 IO.mapOptional("InCStyleCasts", Spaces.InCStyleCasts);852 IO.mapOptional("InConditionalStatements", Spaces.InConditionalStatements);853 IO.mapOptional("InEmptyParentheses", Spaces.InEmptyParentheses);854 IO.mapOptional("Other", Spaces.Other);855 }856};857 858template <> struct ScalarEnumerationTraits<FormatStyle::SpacesInParensStyle> {859 static void enumeration(IO &IO, FormatStyle::SpacesInParensStyle &Value) {860 IO.enumCase(Value, "Never", FormatStyle::SIPO_Never);861 IO.enumCase(Value, "Custom", FormatStyle::SIPO_Custom);862 }863};864 865template <> struct ScalarEnumerationTraits<FormatStyle::TrailingCommaStyle> {866 static void enumeration(IO &IO, FormatStyle::TrailingCommaStyle &Value) {867 IO.enumCase(Value, "None", FormatStyle::TCS_None);868 IO.enumCase(Value, "Wrapped", FormatStyle::TCS_Wrapped);869 }870};871 872template <>873struct ScalarEnumerationTraits<FormatStyle::TrailingCommentsAlignmentKinds> {874 static void enumeration(IO &IO,875 FormatStyle::TrailingCommentsAlignmentKinds &Value) {876 IO.enumCase(Value, "Leave", FormatStyle::TCAS_Leave);877 IO.enumCase(Value, "Always", FormatStyle::TCAS_Always);878 IO.enumCase(Value, "Never", FormatStyle::TCAS_Never);879 }880};881 882template <> struct MappingTraits<FormatStyle::TrailingCommentsAlignmentStyle> {883 static void enumInput(IO &IO,884 FormatStyle::TrailingCommentsAlignmentStyle &Value) {885 IO.enumCase(Value, "Leave",886 FormatStyle::TrailingCommentsAlignmentStyle(887 {FormatStyle::TCAS_Leave, 0, true}));888 889 IO.enumCase(Value, "Always",890 FormatStyle::TrailingCommentsAlignmentStyle(891 {FormatStyle::TCAS_Always, 0, true}));892 893 IO.enumCase(Value, "Never",894 FormatStyle::TrailingCommentsAlignmentStyle(895 {FormatStyle::TCAS_Never, 0, true}));896 897 // For backwards compatibility898 IO.enumCase(Value, "true",899 FormatStyle::TrailingCommentsAlignmentStyle(900 {FormatStyle::TCAS_Always, 0, true}));901 IO.enumCase(Value, "false",902 FormatStyle::TrailingCommentsAlignmentStyle(903 {FormatStyle::TCAS_Never, 0, true}));904 }905 906 static void mapping(IO &IO,907 FormatStyle::TrailingCommentsAlignmentStyle &Value) {908 IO.mapOptional("AlignPPAndNotPP", Value.AlignPPAndNotPP);909 IO.mapOptional("Kind", Value.Kind);910 IO.mapOptional("OverEmptyLines", Value.OverEmptyLines);911 }912};913 914template <> struct ScalarEnumerationTraits<FormatStyle::UseTabStyle> {915 static void enumeration(IO &IO, FormatStyle::UseTabStyle &Value) {916 IO.enumCase(Value, "Never", FormatStyle::UT_Never);917 IO.enumCase(Value, "false", FormatStyle::UT_Never);918 IO.enumCase(Value, "Always", FormatStyle::UT_Always);919 IO.enumCase(Value, "true", FormatStyle::UT_Always);920 IO.enumCase(Value, "ForIndentation", FormatStyle::UT_ForIndentation);921 IO.enumCase(Value, "ForContinuationAndIndentation",922 FormatStyle::UT_ForContinuationAndIndentation);923 IO.enumCase(Value, "AlignWithSpaces", FormatStyle::UT_AlignWithSpaces);924 }925};926 927template <>928struct ScalarEnumerationTraits<929 FormatStyle::WrapNamespaceBodyWithEmptyLinesStyle> {930 static void931 enumeration(IO &IO,932 FormatStyle::WrapNamespaceBodyWithEmptyLinesStyle &Value) {933 IO.enumCase(Value, "Never", FormatStyle::WNBWELS_Never);934 IO.enumCase(Value, "Always", FormatStyle::WNBWELS_Always);935 IO.enumCase(Value, "Leave", FormatStyle::WNBWELS_Leave);936 }937};938 939template <> struct MappingTraits<FormatStyle> {940 static void mapping(IO &IO, FormatStyle &Style) {941 // When reading, read the language first, we need it for getPredefinedStyle.942 IO.mapOptional("Language", Style.Language);943 944 StringRef BasedOnStyle;945 if (IO.outputting()) {946 StringRef Styles[] = {"LLVM", "Google", "Chromium", "Mozilla",947 "WebKit", "GNU", "Microsoft", "clang-format"};948 for (StringRef StyleName : Styles) {949 FormatStyle PredefinedStyle;950 if (getPredefinedStyle(StyleName, Style.Language, &PredefinedStyle) &&951 Style == PredefinedStyle) {952 BasedOnStyle = StyleName;953 break;954 }955 }956 } else {957 IO.mapOptional("BasedOnStyle", BasedOnStyle);958 if (!BasedOnStyle.empty()) {959 FormatStyle::LanguageKind OldLanguage = Style.Language;960 FormatStyle::LanguageKind Language =961 ((FormatStyle *)IO.getContext())->Language;962 if (!getPredefinedStyle(BasedOnStyle, Language, &Style)) {963 IO.setError(Twine("Unknown value for BasedOnStyle: ", BasedOnStyle));964 return;965 }966 Style.Language = OldLanguage;967 }968 }969 970 // Initialize some variables used in the parsing. The using logic is at the971 // end.972 973 // For backward compatibility:974 // The default value of ConstructorInitializerAllOnOneLineOrOnePerLine was975 // false unless BasedOnStyle was Google or Chromium whereas that of976 // AllowAllConstructorInitializersOnNextLine was always true, so the977 // equivalent default value of PackConstructorInitializers is PCIS_NextLine978 // for Google/Chromium or PCIS_BinPack otherwise. If the deprecated options979 // had a non-default value while PackConstructorInitializers has a default980 // value, set the latter to an equivalent non-default value if needed.981 const bool IsGoogleOrChromium = BasedOnStyle.equals_insensitive("google") ||982 BasedOnStyle.equals_insensitive("chromium");983 bool OnCurrentLine = IsGoogleOrChromium;984 bool OnNextLine = true;985 986 bool BreakBeforeInheritanceComma = false;987 bool BreakConstructorInitializersBeforeComma = false;988 989 bool DeriveLineEnding = true;990 bool UseCRLF = false;991 992 bool SpaceInEmptyBlock = false;993 bool SpaceInEmptyParentheses = false;994 bool SpacesInConditionalStatement = false;995 bool SpacesInCStyleCastParentheses = false;996 bool SpacesInParentheses = false;997 998 if (IO.outputting()) {999 IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket);1000 } else {1001 // For backward compatibility.1002 BracketAlignmentStyle LocalBAS = BAS_Align;1003 if (IsGoogleOrChromium) {1004 FormatStyle::LanguageKind Language = Style.Language;1005 if (Language == FormatStyle::LK_None)1006 Language = ((FormatStyle *)IO.getContext())->Language;1007 if (Language == FormatStyle::LK_JavaScript)1008 LocalBAS = BAS_AlwaysBreak;1009 else if (Language == FormatStyle::LK_Java)1010 LocalBAS = BAS_DontAlign;1011 } else if (BasedOnStyle.equals_insensitive("webkit")) {1012 LocalBAS = BAS_DontAlign;1013 }1014 IO.mapOptional("AlignAfterOpenBracket", LocalBAS);1015 Style.BreakAfterOpenBracketBracedList = false;1016 Style.BreakAfterOpenBracketFunction = false;1017 Style.BreakAfterOpenBracketIf = false;1018 Style.BreakAfterOpenBracketLoop = false;1019 Style.BreakAfterOpenBracketSwitch = false;1020 Style.BreakBeforeCloseBracketBracedList = false;1021 Style.BreakBeforeCloseBracketFunction = false;1022 Style.BreakBeforeCloseBracketIf = false;1023 Style.BreakBeforeCloseBracketLoop = false;1024 Style.BreakBeforeCloseBracketSwitch = false;1025 1026 switch (LocalBAS) {1027 case BAS_DontAlign:1028 Style.AlignAfterOpenBracket = false;1029 break;1030 case BAS_BlockIndent:1031 Style.BreakBeforeCloseBracketBracedList = true;1032 Style.BreakBeforeCloseBracketFunction = true;1033 Style.BreakBeforeCloseBracketIf = true;1034 [[fallthrough]];1035 case BAS_AlwaysBreak:1036 Style.BreakAfterOpenBracketBracedList = true;1037 Style.BreakAfterOpenBracketFunction = true;1038 Style.BreakAfterOpenBracketIf = true;1039 [[fallthrough]];1040 case BAS_Align:1041 Style.AlignAfterOpenBracket = true;1042 break;1043 }1044 }1045 1046 // For backward compatibility.1047 if (!IO.outputting()) {1048 IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlines);1049 IO.mapOptional("AllowAllConstructorInitializersOnNextLine", OnNextLine);1050 IO.mapOptional("AlwaysBreakAfterReturnType", Style.BreakAfterReturnType);1051 IO.mapOptional("AlwaysBreakTemplateDeclarations",1052 Style.BreakTemplateDeclarations);1053 IO.mapOptional("BreakBeforeInheritanceComma",1054 BreakBeforeInheritanceComma);1055 IO.mapOptional("BreakConstructorInitializersBeforeComma",1056 BreakConstructorInitializersBeforeComma);1057 IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine",1058 OnCurrentLine);1059 IO.mapOptional("DeriveLineEnding", DeriveLineEnding);1060 IO.mapOptional("DerivePointerBinding", Style.DerivePointerAlignment);1061 IO.mapOptional("KeepEmptyLinesAtEOF", Style.KeepEmptyLines.AtEndOfFile);1062 IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks",1063 Style.KeepEmptyLines.AtStartOfBlock);1064 IO.mapOptional("IndentFunctionDeclarationAfterType",1065 Style.IndentWrappedFunctionNames);1066 IO.mapOptional("IndentRequires", Style.IndentRequiresClause);1067 IO.mapOptional("PointerBindsToType", Style.PointerAlignment);1068 IO.mapOptional("SpaceAfterControlStatementKeyword",1069 Style.SpaceBeforeParens);1070 IO.mapOptional("SpaceInEmptyBlock", SpaceInEmptyBlock);1071 IO.mapOptional("SpaceInEmptyParentheses", SpaceInEmptyParentheses);1072 IO.mapOptional("SpacesInConditionalStatement",1073 SpacesInConditionalStatement);1074 IO.mapOptional("SpacesInCStyleCastParentheses",1075 SpacesInCStyleCastParentheses);1076 IO.mapOptional("SpacesInParentheses", SpacesInParentheses);1077 IO.mapOptional("UseCRLF", UseCRLF);1078 }1079 1080 IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset);1081 IO.mapOptional("AlignArrayOfStructures", Style.AlignArrayOfStructures);1082 IO.mapOptional("AlignConsecutiveAssignments",1083 Style.AlignConsecutiveAssignments);1084 IO.mapOptional("AlignConsecutiveBitFields",1085 Style.AlignConsecutiveBitFields);1086 IO.mapOptional("AlignConsecutiveDeclarations",1087 Style.AlignConsecutiveDeclarations);1088 IO.mapOptional("AlignConsecutiveMacros", Style.AlignConsecutiveMacros);1089 IO.mapOptional("AlignConsecutiveShortCaseStatements",1090 Style.AlignConsecutiveShortCaseStatements);1091 IO.mapOptional("AlignConsecutiveTableGenBreakingDAGArgColons",1092 Style.AlignConsecutiveTableGenBreakingDAGArgColons);1093 IO.mapOptional("AlignConsecutiveTableGenCondOperatorColons",1094 Style.AlignConsecutiveTableGenCondOperatorColons);1095 IO.mapOptional("AlignConsecutiveTableGenDefinitionColons",1096 Style.AlignConsecutiveTableGenDefinitionColons);1097 IO.mapOptional("AlignEscapedNewlines", Style.AlignEscapedNewlines);1098 IO.mapOptional("AlignOperands", Style.AlignOperands);1099 IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments);1100 IO.mapOptional("AllowAllArgumentsOnNextLine",1101 Style.AllowAllArgumentsOnNextLine);1102 IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine",1103 Style.AllowAllParametersOfDeclarationOnNextLine);1104 IO.mapOptional("AllowBreakBeforeNoexceptSpecifier",1105 Style.AllowBreakBeforeNoexceptSpecifier);1106 IO.mapOptional("AllowBreakBeforeQtProperty",1107 Style.AllowBreakBeforeQtProperty);1108 IO.mapOptional("AllowShortBlocksOnASingleLine",1109 Style.AllowShortBlocksOnASingleLine);1110 IO.mapOptional("AllowShortCaseExpressionOnASingleLine",1111 Style.AllowShortCaseExpressionOnASingleLine);1112 IO.mapOptional("AllowShortCaseLabelsOnASingleLine",1113 Style.AllowShortCaseLabelsOnASingleLine);1114 IO.mapOptional("AllowShortCompoundRequirementOnASingleLine",1115 Style.AllowShortCompoundRequirementOnASingleLine);1116 IO.mapOptional("AllowShortEnumsOnASingleLine",1117 Style.AllowShortEnumsOnASingleLine);1118 IO.mapOptional("AllowShortFunctionsOnASingleLine",1119 Style.AllowShortFunctionsOnASingleLine);1120 IO.mapOptional("AllowShortIfStatementsOnASingleLine",1121 Style.AllowShortIfStatementsOnASingleLine);1122 IO.mapOptional("AllowShortLambdasOnASingleLine",1123 Style.AllowShortLambdasOnASingleLine);1124 IO.mapOptional("AllowShortLoopsOnASingleLine",1125 Style.AllowShortLoopsOnASingleLine);1126 IO.mapOptional("AllowShortNamespacesOnASingleLine",1127 Style.AllowShortNamespacesOnASingleLine);1128 IO.mapOptional("AlwaysBreakAfterDefinitionReturnType",1129 Style.AlwaysBreakAfterDefinitionReturnType);1130 IO.mapOptional("AlwaysBreakBeforeMultilineStrings",1131 Style.AlwaysBreakBeforeMultilineStrings);1132 IO.mapOptional("AttributeMacros", Style.AttributeMacros);1133 IO.mapOptional("BinPackArguments", Style.BinPackArguments);1134 IO.mapOptional("BinPackLongBracedList", Style.BinPackLongBracedList);1135 IO.mapOptional("BinPackParameters", Style.BinPackParameters);1136 IO.mapOptional("BitFieldColonSpacing", Style.BitFieldColonSpacing);1137 IO.mapOptional("BracedInitializerIndentWidth",1138 Style.BracedInitializerIndentWidth);1139 IO.mapOptional("BraceWrapping", Style.BraceWrapping);1140 IO.mapOptional("BreakAdjacentStringLiterals",1141 Style.BreakAdjacentStringLiterals);1142 IO.mapOptional("BreakAfterAttributes", Style.BreakAfterAttributes);1143 IO.mapOptional("BreakAfterJavaFieldAnnotations",1144 Style.BreakAfterJavaFieldAnnotations);1145 IO.mapOptional("BreakAfterOpenBracketBracedList",1146 Style.BreakAfterOpenBracketBracedList);1147 IO.mapOptional("BreakAfterOpenBracketFunction",1148 Style.BreakAfterOpenBracketFunction);1149 IO.mapOptional("BreakAfterOpenBracketIf", Style.BreakAfterOpenBracketIf);1150 IO.mapOptional("BreakAfterOpenBracketLoop",1151 Style.BreakAfterOpenBracketLoop);1152 IO.mapOptional("BreakAfterOpenBracketSwitch",1153 Style.BreakAfterOpenBracketSwitch);1154 IO.mapOptional("BreakAfterReturnType", Style.BreakAfterReturnType);1155 IO.mapOptional("BreakArrays", Style.BreakArrays);1156 IO.mapOptional("BreakBeforeBinaryOperators",1157 Style.BreakBeforeBinaryOperators);1158 IO.mapOptional("BreakBeforeCloseBracketBracedList",1159 Style.BreakBeforeCloseBracketBracedList);1160 IO.mapOptional("BreakBeforeCloseBracketFunction",1161 Style.BreakBeforeCloseBracketFunction);1162 IO.mapOptional("BreakBeforeCloseBracketIf",1163 Style.BreakBeforeCloseBracketIf);1164 IO.mapOptional("BreakBeforeCloseBracketLoop",1165 Style.BreakBeforeCloseBracketLoop);1166 IO.mapOptional("BreakBeforeCloseBracketSwitch",1167 Style.BreakBeforeCloseBracketSwitch);1168 IO.mapOptional("BreakBeforeConceptDeclarations",1169 Style.BreakBeforeConceptDeclarations);1170 IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);1171 IO.mapOptional("BreakBeforeInlineASMColon",1172 Style.BreakBeforeInlineASMColon);1173 IO.mapOptional("BreakBeforeTemplateCloser",1174 Style.BreakBeforeTemplateCloser);1175 IO.mapOptional("BreakBeforeTernaryOperators",1176 Style.BreakBeforeTernaryOperators);1177 IO.mapOptional("BreakBinaryOperations", Style.BreakBinaryOperations);1178 IO.mapOptional("BreakConstructorInitializers",1179 Style.BreakConstructorInitializers);1180 IO.mapOptional("BreakFunctionDefinitionParameters",1181 Style.BreakFunctionDefinitionParameters);1182 IO.mapOptional("BreakInheritanceList", Style.BreakInheritanceList);1183 IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals);1184 IO.mapOptional("BreakTemplateDeclarations",1185 Style.BreakTemplateDeclarations);1186 IO.mapOptional("ColumnLimit", Style.ColumnLimit);1187 IO.mapOptional("CommentPragmas", Style.CommentPragmas);1188 IO.mapOptional("CompactNamespaces", Style.CompactNamespaces);1189 IO.mapOptional("ConstructorInitializerIndentWidth",1190 Style.ConstructorInitializerIndentWidth);1191 IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth);1192 IO.mapOptional("Cpp11BracedListStyle", Style.Cpp11BracedListStyle);1193 IO.mapOptional("DerivePointerAlignment", Style.DerivePointerAlignment);1194 IO.mapOptional("DisableFormat", Style.DisableFormat);1195 IO.mapOptional("EmptyLineAfterAccessModifier",1196 Style.EmptyLineAfterAccessModifier);1197 IO.mapOptional("EmptyLineBeforeAccessModifier",1198 Style.EmptyLineBeforeAccessModifier);1199 IO.mapOptional("EnumTrailingComma", Style.EnumTrailingComma);1200 IO.mapOptional("ExperimentalAutoDetectBinPacking",1201 Style.ExperimentalAutoDetectBinPacking);1202 IO.mapOptional("FixNamespaceComments", Style.FixNamespaceComments);1203 IO.mapOptional("ForEachMacros", Style.ForEachMacros);1204 IO.mapOptional("IfMacros", Style.IfMacros);1205 IO.mapOptional("IncludeBlocks", Style.IncludeStyle.IncludeBlocks);1206 IO.mapOptional("IncludeCategories", Style.IncludeStyle.IncludeCategories);1207 IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex);1208 IO.mapOptional("IncludeIsMainSourceRegex",1209 Style.IncludeStyle.IncludeIsMainSourceRegex);1210 IO.mapOptional("IndentAccessModifiers", Style.IndentAccessModifiers);1211 IO.mapOptional("IndentCaseBlocks", Style.IndentCaseBlocks);1212 IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);1213 IO.mapOptional("IndentExportBlock", Style.IndentExportBlock);1214 IO.mapOptional("IndentExternBlock", Style.IndentExternBlock);1215 IO.mapOptional("IndentGotoLabels", Style.IndentGotoLabels);1216 IO.mapOptional("IndentPPDirectives", Style.IndentPPDirectives);1217 IO.mapOptional("IndentRequiresClause", Style.IndentRequiresClause);1218 IO.mapOptional("IndentWidth", Style.IndentWidth);1219 IO.mapOptional("IndentWrappedFunctionNames",1220 Style.IndentWrappedFunctionNames);1221 IO.mapOptional("InsertBraces", Style.InsertBraces);1222 IO.mapOptional("InsertNewlineAtEOF", Style.InsertNewlineAtEOF);1223 IO.mapOptional("InsertTrailingCommas", Style.InsertTrailingCommas);1224 IO.mapOptional("IntegerLiteralSeparator", Style.IntegerLiteralSeparator);1225 IO.mapOptional("JavaImportGroups", Style.JavaImportGroups);1226 IO.mapOptional("JavaScriptQuotes", Style.JavaScriptQuotes);1227 IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports);1228 IO.mapOptional("KeepEmptyLines", Style.KeepEmptyLines);1229 IO.mapOptional("KeepFormFeed", Style.KeepFormFeed);1230 IO.mapOptional("LambdaBodyIndentation", Style.LambdaBodyIndentation);1231 IO.mapOptional("LineEnding", Style.LineEnding);1232 IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin);1233 IO.mapOptional("MacroBlockEnd", Style.MacroBlockEnd);1234 IO.mapOptional("Macros", Style.Macros);1235 IO.mapOptional("MacrosSkippedByRemoveParentheses",1236 Style.MacrosSkippedByRemoveParentheses);1237 IO.mapOptional("MainIncludeChar", Style.IncludeStyle.MainIncludeChar);1238 IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep);1239 IO.mapOptional("NamespaceIndentation", Style.NamespaceIndentation);1240 IO.mapOptional("NamespaceMacros", Style.NamespaceMacros);1241 IO.mapOptional("NumericLiteralCase", Style.NumericLiteralCase);1242 IO.mapOptional("ObjCBinPackProtocolList", Style.ObjCBinPackProtocolList);1243 IO.mapOptional("ObjCBlockIndentWidth", Style.ObjCBlockIndentWidth);1244 IO.mapOptional("ObjCBreakBeforeNestedBlockParam",1245 Style.ObjCBreakBeforeNestedBlockParam);1246 IO.mapOptional("ObjCPropertyAttributeOrder",1247 Style.ObjCPropertyAttributeOrder);1248 IO.mapOptional("ObjCSpaceAfterProperty", Style.ObjCSpaceAfterProperty);1249 IO.mapOptional("ObjCSpaceBeforeProtocolList",1250 Style.ObjCSpaceBeforeProtocolList);1251 IO.mapOptional("OneLineFormatOffRegex", Style.OneLineFormatOffRegex);1252 IO.mapOptional("PackConstructorInitializers",1253 Style.PackConstructorInitializers);1254 IO.mapOptional("PenaltyBreakAssignment", Style.PenaltyBreakAssignment);1255 IO.mapOptional("PenaltyBreakBeforeFirstCallParameter",1256 Style.PenaltyBreakBeforeFirstCallParameter);1257 IO.mapOptional("PenaltyBreakBeforeMemberAccess",1258 Style.PenaltyBreakBeforeMemberAccess);1259 IO.mapOptional("PenaltyBreakComment", Style.PenaltyBreakComment);1260 IO.mapOptional("PenaltyBreakFirstLessLess",1261 Style.PenaltyBreakFirstLessLess);1262 IO.mapOptional("PenaltyBreakOpenParenthesis",1263 Style.PenaltyBreakOpenParenthesis);1264 IO.mapOptional("PenaltyBreakScopeResolution",1265 Style.PenaltyBreakScopeResolution);1266 IO.mapOptional("PenaltyBreakString", Style.PenaltyBreakString);1267 IO.mapOptional("PenaltyBreakTemplateDeclaration",1268 Style.PenaltyBreakTemplateDeclaration);1269 IO.mapOptional("PenaltyExcessCharacter", Style.PenaltyExcessCharacter);1270 IO.mapOptional("PenaltyIndentedWhitespace",1271 Style.PenaltyIndentedWhitespace);1272 IO.mapOptional("PenaltyReturnTypeOnItsOwnLine",1273 Style.PenaltyReturnTypeOnItsOwnLine);1274 IO.mapOptional("PointerAlignment", Style.PointerAlignment);1275 IO.mapOptional("PPIndentWidth", Style.PPIndentWidth);1276 IO.mapOptional("QualifierAlignment", Style.QualifierAlignment);1277 // Default Order for Left/Right based Qualifier alignment.1278 if (Style.QualifierAlignment == FormatStyle::QAS_Right)1279 Style.QualifierOrder = {"type", "const", "volatile"};1280 else if (Style.QualifierAlignment == FormatStyle::QAS_Left)1281 Style.QualifierOrder = {"const", "volatile", "type"};1282 else if (Style.QualifierAlignment == FormatStyle::QAS_Custom)1283 IO.mapOptional("QualifierOrder", Style.QualifierOrder);1284 IO.mapOptional("RawStringFormats", Style.RawStringFormats);1285 IO.mapOptional("ReferenceAlignment", Style.ReferenceAlignment);1286 IO.mapOptional("ReflowComments", Style.ReflowComments);1287 IO.mapOptional("RemoveBracesLLVM", Style.RemoveBracesLLVM);1288 IO.mapOptional("RemoveEmptyLinesInUnwrappedLines",1289 Style.RemoveEmptyLinesInUnwrappedLines);1290 IO.mapOptional("RemoveParentheses", Style.RemoveParentheses);1291 IO.mapOptional("RemoveSemicolon", Style.RemoveSemicolon);1292 IO.mapOptional("RequiresClausePosition", Style.RequiresClausePosition);1293 IO.mapOptional("RequiresExpressionIndentation",1294 Style.RequiresExpressionIndentation);1295 IO.mapOptional("SeparateDefinitionBlocks", Style.SeparateDefinitionBlocks);1296 IO.mapOptional("ShortNamespaceLines", Style.ShortNamespaceLines);1297 IO.mapOptional("SkipMacroDefinitionBody", Style.SkipMacroDefinitionBody);1298 IO.mapOptional("SortIncludes", Style.SortIncludes);1299 IO.mapOptional("SortJavaStaticImport", Style.SortJavaStaticImport);1300 IO.mapOptional("SortUsingDeclarations", Style.SortUsingDeclarations);1301 IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast);1302 IO.mapOptional("SpaceAfterLogicalNot", Style.SpaceAfterLogicalNot);1303 IO.mapOptional("SpaceAfterOperatorKeyword",1304 Style.SpaceAfterOperatorKeyword);1305 IO.mapOptional("SpaceAfterTemplateKeyword",1306 Style.SpaceAfterTemplateKeyword);1307 IO.mapOptional("SpaceAroundPointerQualifiers",1308 Style.SpaceAroundPointerQualifiers);1309 IO.mapOptional("SpaceBeforeAssignmentOperators",1310 Style.SpaceBeforeAssignmentOperators);1311 IO.mapOptional("SpaceBeforeCaseColon", Style.SpaceBeforeCaseColon);1312 IO.mapOptional("SpaceBeforeCpp11BracedList",1313 Style.SpaceBeforeCpp11BracedList);1314 IO.mapOptional("SpaceBeforeCtorInitializerColon",1315 Style.SpaceBeforeCtorInitializerColon);1316 IO.mapOptional("SpaceBeforeInheritanceColon",1317 Style.SpaceBeforeInheritanceColon);1318 IO.mapOptional("SpaceBeforeJsonColon", Style.SpaceBeforeJsonColon);1319 IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);1320 IO.mapOptional("SpaceBeforeParensOptions", Style.SpaceBeforeParensOptions);1321 IO.mapOptional("SpaceBeforeRangeBasedForLoopColon",1322 Style.SpaceBeforeRangeBasedForLoopColon);1323 IO.mapOptional("SpaceBeforeSquareBrackets",1324 Style.SpaceBeforeSquareBrackets);1325 IO.mapOptional("SpaceInEmptyBraces", Style.SpaceInEmptyBraces);1326 IO.mapOptional("SpacesBeforeTrailingComments",1327 Style.SpacesBeforeTrailingComments);1328 IO.mapOptional("SpacesInAngles", Style.SpacesInAngles);1329 IO.mapOptional("SpacesInContainerLiterals",1330 Style.SpacesInContainerLiterals);1331 IO.mapOptional("SpacesInLineCommentPrefix",1332 Style.SpacesInLineCommentPrefix);1333 IO.mapOptional("SpacesInParens", Style.SpacesInParens);1334 IO.mapOptional("SpacesInParensOptions", Style.SpacesInParensOptions);1335 IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets);1336 IO.mapOptional("Standard", Style.Standard);1337 IO.mapOptional("StatementAttributeLikeMacros",1338 Style.StatementAttributeLikeMacros);1339 IO.mapOptional("StatementMacros", Style.StatementMacros);1340 IO.mapOptional("TableGenBreakingDAGArgOperators",1341 Style.TableGenBreakingDAGArgOperators);1342 IO.mapOptional("TableGenBreakInsideDAGArg",1343 Style.TableGenBreakInsideDAGArg);1344 IO.mapOptional("TabWidth", Style.TabWidth);1345 IO.mapOptional("TemplateNames", Style.TemplateNames);1346 IO.mapOptional("TypeNames", Style.TypeNames);1347 IO.mapOptional("TypenameMacros", Style.TypenameMacros);1348 IO.mapOptional("UseTab", Style.UseTab);1349 IO.mapOptional("VariableTemplates", Style.VariableTemplates);1350 IO.mapOptional("VerilogBreakBetweenInstancePorts",1351 Style.VerilogBreakBetweenInstancePorts);1352 IO.mapOptional("WhitespaceSensitiveMacros",1353 Style.WhitespaceSensitiveMacros);1354 IO.mapOptional("WrapNamespaceBodyWithEmptyLines",1355 Style.WrapNamespaceBodyWithEmptyLines);1356 1357 // If AlwaysBreakAfterDefinitionReturnType was specified but1358 // BreakAfterReturnType was not, initialize the latter from the former for1359 // backwards compatibility.1360 if (Style.AlwaysBreakAfterDefinitionReturnType != FormatStyle::DRTBS_None &&1361 Style.BreakAfterReturnType == FormatStyle::RTBS_None) {1362 if (Style.AlwaysBreakAfterDefinitionReturnType ==1363 FormatStyle::DRTBS_All) {1364 Style.BreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;1365 } else if (Style.AlwaysBreakAfterDefinitionReturnType ==1366 FormatStyle::DRTBS_TopLevel) {1367 Style.BreakAfterReturnType = FormatStyle::RTBS_TopLevelDefinitions;1368 }1369 }1370 1371 // If BreakBeforeInheritanceComma was specified but BreakInheritance was1372 // not, initialize the latter from the former for backwards compatibility.1373 if (BreakBeforeInheritanceComma &&1374 Style.BreakInheritanceList == FormatStyle::BILS_BeforeColon) {1375 Style.BreakInheritanceList = FormatStyle::BILS_BeforeComma;1376 }1377 1378 // If BreakConstructorInitializersBeforeComma was specified but1379 // BreakConstructorInitializers was not, initialize the latter from the1380 // former for backwards compatibility.1381 if (BreakConstructorInitializersBeforeComma &&1382 Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon) {1383 Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;1384 }1385 1386 if (!IsGoogleOrChromium) {1387 if (Style.PackConstructorInitializers == FormatStyle::PCIS_BinPack &&1388 OnCurrentLine) {1389 Style.PackConstructorInitializers = OnNextLine1390 ? FormatStyle::PCIS_NextLine1391 : FormatStyle::PCIS_CurrentLine;1392 }1393 } else if (Style.PackConstructorInitializers ==1394 FormatStyle::PCIS_NextLine) {1395 if (!OnCurrentLine)1396 Style.PackConstructorInitializers = FormatStyle::PCIS_BinPack;1397 else if (!OnNextLine)1398 Style.PackConstructorInitializers = FormatStyle::PCIS_CurrentLine;1399 }1400 1401 if (Style.LineEnding == FormatStyle::LE_DeriveLF) {1402 if (!DeriveLineEnding)1403 Style.LineEnding = UseCRLF ? FormatStyle::LE_CRLF : FormatStyle::LE_LF;1404 else if (UseCRLF)1405 Style.LineEnding = FormatStyle::LE_DeriveCRLF;1406 }1407 1408 // If SpaceInEmptyBlock was specified but SpaceInEmptyBraces was not,1409 // initialize the latter from the former for backward compatibility.1410 if (SpaceInEmptyBlock &&1411 Style.SpaceInEmptyBraces == FormatStyle::SIEB_Never) {1412 Style.SpaceInEmptyBraces = FormatStyle::SIEB_Block;1413 }1414 1415 if (Style.SpacesInParens != FormatStyle::SIPO_Custom &&1416 (SpacesInParentheses || SpaceInEmptyParentheses ||1417 SpacesInConditionalStatement || SpacesInCStyleCastParentheses)) {1418 if (SpacesInParentheses) {1419 // For backward compatibility.1420 Style.SpacesInParensOptions.ExceptDoubleParentheses = false;1421 Style.SpacesInParensOptions.InConditionalStatements = true;1422 Style.SpacesInParensOptions.InCStyleCasts =1423 SpacesInCStyleCastParentheses;1424 Style.SpacesInParensOptions.InEmptyParentheses =1425 SpaceInEmptyParentheses;1426 Style.SpacesInParensOptions.Other = true;1427 } else {1428 Style.SpacesInParensOptions = {};1429 Style.SpacesInParensOptions.InConditionalStatements =1430 SpacesInConditionalStatement;1431 Style.SpacesInParensOptions.InCStyleCasts =1432 SpacesInCStyleCastParentheses;1433 Style.SpacesInParensOptions.InEmptyParentheses =1434 SpaceInEmptyParentheses;1435 }1436 Style.SpacesInParens = FormatStyle::SIPO_Custom;1437 }1438 }1439};1440 1441// Allows to read vector<FormatStyle> while keeping default values.1442// IO.getContext() should contain a pointer to the FormatStyle structure, that1443// will be used to get default values for missing keys.1444// If the first element has no Language specified, it will be treated as the1445// default one for the following elements.1446template <> struct DocumentListTraits<std::vector<FormatStyle>> {1447 static size_t size(IO &IO, std::vector<FormatStyle> &Seq) {1448 return Seq.size();1449 }1450 static FormatStyle &element(IO &IO, std::vector<FormatStyle> &Seq,1451 size_t Index) {1452 if (Index >= Seq.size()) {1453 assert(Index == Seq.size());1454 FormatStyle Template;1455 if (!Seq.empty() && Seq[0].Language == FormatStyle::LK_None) {1456 Template = Seq[0];1457 } else {1458 Template = *((const FormatStyle *)IO.getContext());1459 Template.Language = FormatStyle::LK_None;1460 }1461 Seq.resize(Index + 1, Template);1462 }1463 return Seq[Index];1464 }1465};1466} // namespace yaml1467} // namespace llvm1468 1469namespace clang {1470namespace format {1471 1472const std::error_category &getParseCategory() {1473 static const ParseErrorCategory C{};1474 return C;1475}1476std::error_code make_error_code(ParseError e) {1477 return std::error_code(static_cast<int>(e), getParseCategory());1478}1479 1480inline llvm::Error make_string_error(const Twine &Message) {1481 return llvm::make_error<llvm::StringError>(Message,1482 llvm::inconvertibleErrorCode());1483}1484 1485const char *ParseErrorCategory::name() const noexcept {1486 return "clang-format.parse_error";1487}1488 1489std::string ParseErrorCategory::message(int EV) const {1490 switch (static_cast<ParseError>(EV)) {1491 case ParseError::Success:1492 return "Success";1493 case ParseError::Error:1494 return "Invalid argument";1495 case ParseError::Unsuitable:1496 return "Unsuitable";1497 case ParseError::BinPackTrailingCommaConflict:1498 return "trailing comma insertion cannot be used with bin packing";1499 case ParseError::InvalidQualifierSpecified:1500 return "Invalid qualifier specified in QualifierOrder";1501 case ParseError::DuplicateQualifierSpecified:1502 return "Duplicate qualifier specified in QualifierOrder";1503 case ParseError::MissingQualifierType:1504 return "Missing type in QualifierOrder";1505 case ParseError::MissingQualifierOrder:1506 return "Missing QualifierOrder";1507 }1508 llvm_unreachable("unexpected parse error");1509}1510 1511static void expandPresetsBraceWrapping(FormatStyle &Expanded) {1512 if (Expanded.BreakBeforeBraces == FormatStyle::BS_Custom)1513 return;1514 Expanded.BraceWrapping = {/*AfterCaseLabel=*/false,1515 /*AfterClass=*/false,1516 /*AfterControlStatement=*/FormatStyle::BWACS_Never,1517 /*AfterEnum=*/false,1518 /*AfterFunction=*/false,1519 /*AfterNamespace=*/false,1520 /*AfterObjCDeclaration=*/false,1521 /*AfterStruct=*/false,1522 /*AfterUnion=*/false,1523 /*AfterExternBlock=*/false,1524 /*BeforeCatch=*/false,1525 /*BeforeElse=*/false,1526 /*BeforeLambdaBody=*/false,1527 /*BeforeWhile=*/false,1528 /*IndentBraces=*/false,1529 /*SplitEmptyFunction=*/true,1530 /*SplitEmptyRecord=*/true,1531 /*SplitEmptyNamespace=*/true};1532 switch (Expanded.BreakBeforeBraces) {1533 case FormatStyle::BS_Linux:1534 Expanded.BraceWrapping.AfterClass = true;1535 Expanded.BraceWrapping.AfterFunction = true;1536 Expanded.BraceWrapping.AfterNamespace = true;1537 break;1538 case FormatStyle::BS_Mozilla:1539 Expanded.BraceWrapping.AfterClass = true;1540 Expanded.BraceWrapping.AfterEnum = true;1541 Expanded.BraceWrapping.AfterFunction = true;1542 Expanded.BraceWrapping.AfterStruct = true;1543 Expanded.BraceWrapping.AfterUnion = true;1544 Expanded.BraceWrapping.AfterExternBlock = true;1545 Expanded.BraceWrapping.SplitEmptyFunction = true;1546 Expanded.BraceWrapping.SplitEmptyRecord = false;1547 break;1548 case FormatStyle::BS_Stroustrup:1549 Expanded.BraceWrapping.AfterFunction = true;1550 Expanded.BraceWrapping.BeforeCatch = true;1551 Expanded.BraceWrapping.BeforeElse = true;1552 break;1553 case FormatStyle::BS_Allman:1554 Expanded.BraceWrapping.AfterCaseLabel = true;1555 Expanded.BraceWrapping.AfterClass = true;1556 Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;1557 Expanded.BraceWrapping.AfterEnum = true;1558 Expanded.BraceWrapping.AfterFunction = true;1559 Expanded.BraceWrapping.AfterNamespace = true;1560 Expanded.BraceWrapping.AfterObjCDeclaration = true;1561 Expanded.BraceWrapping.AfterStruct = true;1562 Expanded.BraceWrapping.AfterUnion = true;1563 Expanded.BraceWrapping.AfterExternBlock = true;1564 Expanded.BraceWrapping.BeforeCatch = true;1565 Expanded.BraceWrapping.BeforeElse = true;1566 Expanded.BraceWrapping.BeforeLambdaBody = true;1567 break;1568 case FormatStyle::BS_Whitesmiths:1569 Expanded.BraceWrapping.AfterCaseLabel = true;1570 Expanded.BraceWrapping.AfterClass = true;1571 Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;1572 Expanded.BraceWrapping.AfterEnum = true;1573 Expanded.BraceWrapping.AfterFunction = true;1574 Expanded.BraceWrapping.AfterNamespace = true;1575 Expanded.BraceWrapping.AfterObjCDeclaration = true;1576 Expanded.BraceWrapping.AfterStruct = true;1577 Expanded.BraceWrapping.AfterExternBlock = true;1578 Expanded.BraceWrapping.BeforeCatch = true;1579 Expanded.BraceWrapping.BeforeElse = true;1580 Expanded.BraceWrapping.BeforeLambdaBody = true;1581 break;1582 case FormatStyle::BS_GNU:1583 Expanded.BraceWrapping = {1584 /*AfterCaseLabel=*/true,1585 /*AfterClass=*/true,1586 /*AfterControlStatement=*/FormatStyle::BWACS_Always,1587 /*AfterEnum=*/true,1588 /*AfterFunction=*/true,1589 /*AfterNamespace=*/true,1590 /*AfterObjCDeclaration=*/true,1591 /*AfterStruct=*/true,1592 /*AfterUnion=*/true,1593 /*AfterExternBlock=*/true,1594 /*BeforeCatch=*/true,1595 /*BeforeElse=*/true,1596 /*BeforeLambdaBody=*/true,1597 /*BeforeWhile=*/true,1598 /*IndentBraces=*/true,1599 /*SplitEmptyFunction=*/true,1600 /*SplitEmptyRecord=*/true,1601 /*SplitEmptyNamespace=*/true};1602 break;1603 case FormatStyle::BS_WebKit:1604 Expanded.BraceWrapping.AfterFunction = true;1605 break;1606 default:1607 break;1608 }1609}1610 1611static void expandPresetsSpaceBeforeParens(FormatStyle &Expanded) {1612 if (Expanded.SpaceBeforeParens == FormatStyle::SBPO_Custom)1613 return;1614 // Reset all flags1615 Expanded.SpaceBeforeParensOptions = {};1616 Expanded.SpaceBeforeParensOptions.AfterPlacementOperator = true;1617 1618 switch (Expanded.SpaceBeforeParens) {1619 case FormatStyle::SBPO_ControlStatements:1620 Expanded.SpaceBeforeParensOptions.AfterControlStatements = true;1621 Expanded.SpaceBeforeParensOptions.AfterForeachMacros = true;1622 Expanded.SpaceBeforeParensOptions.AfterIfMacros = true;1623 break;1624 case FormatStyle::SBPO_ControlStatementsExceptControlMacros:1625 Expanded.SpaceBeforeParensOptions.AfterControlStatements = true;1626 break;1627 case FormatStyle::SBPO_NonEmptyParentheses:1628 Expanded.SpaceBeforeParensOptions.BeforeNonEmptyParentheses = true;1629 break;1630 default:1631 break;1632 }1633}1634 1635static void expandPresetsSpacesInParens(FormatStyle &Expanded) {1636 if (Expanded.SpacesInParens == FormatStyle::SIPO_Custom)1637 return;1638 assert(Expanded.SpacesInParens == FormatStyle::SIPO_Never);1639 // Reset all flags1640 Expanded.SpacesInParensOptions = {};1641}1642 1643FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {1644 FormatStyle LLVMStyle;1645 LLVMStyle.AccessModifierOffset = -2;1646 LLVMStyle.AlignAfterOpenBracket = true;1647 LLVMStyle.AlignArrayOfStructures = FormatStyle::AIAS_None;1648 LLVMStyle.AlignConsecutiveAssignments = {};1649 LLVMStyle.AlignConsecutiveAssignments.PadOperators = true;1650 LLVMStyle.AlignConsecutiveBitFields = {};1651 LLVMStyle.AlignConsecutiveDeclarations = {};1652 LLVMStyle.AlignConsecutiveDeclarations.AlignFunctionDeclarations = true;1653 LLVMStyle.AlignConsecutiveMacros = {};1654 LLVMStyle.AlignConsecutiveShortCaseStatements = {};1655 LLVMStyle.AlignConsecutiveTableGenBreakingDAGArgColons = {};1656 LLVMStyle.AlignConsecutiveTableGenCondOperatorColons = {};1657 LLVMStyle.AlignConsecutiveTableGenDefinitionColons = {};1658 LLVMStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right;1659 LLVMStyle.AlignOperands = FormatStyle::OAS_Align;1660 LLVMStyle.AlignTrailingComments = {};1661 LLVMStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Always;1662 LLVMStyle.AlignTrailingComments.OverEmptyLines = 0;1663 LLVMStyle.AlignTrailingComments.AlignPPAndNotPP = true;1664 LLVMStyle.AllowAllArgumentsOnNextLine = true;1665 LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;1666 LLVMStyle.AllowBreakBeforeNoexceptSpecifier = FormatStyle::BBNSS_Never;1667 LLVMStyle.AllowBreakBeforeQtProperty = false;1668 LLVMStyle.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never;1669 LLVMStyle.AllowShortCaseExpressionOnASingleLine = true;1670 LLVMStyle.AllowShortCaseLabelsOnASingleLine = false;1671 LLVMStyle.AllowShortCompoundRequirementOnASingleLine = true;1672 LLVMStyle.AllowShortEnumsOnASingleLine = true;1673 LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;1674 LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;1675 LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All;1676 LLVMStyle.AllowShortLoopsOnASingleLine = false;1677 LLVMStyle.AllowShortNamespacesOnASingleLine = false;1678 LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;1679 LLVMStyle.AlwaysBreakBeforeMultilineStrings = false;1680 LLVMStyle.AttributeMacros.push_back("__capability");1681 LLVMStyle.BinPackArguments = true;1682 LLVMStyle.BinPackLongBracedList = true;1683 LLVMStyle.BinPackParameters = FormatStyle::BPPS_BinPack;1684 LLVMStyle.BitFieldColonSpacing = FormatStyle::BFCS_Both;1685 LLVMStyle.BracedInitializerIndentWidth = -1;1686 LLVMStyle.BraceWrapping = {/*AfterCaseLabel=*/false,1687 /*AfterClass=*/false,1688 /*AfterControlStatement=*/FormatStyle::BWACS_Never,1689 /*AfterEnum=*/false,1690 /*AfterFunction=*/false,1691 /*AfterNamespace=*/false,1692 /*AfterObjCDeclaration=*/false,1693 /*AfterStruct=*/false,1694 /*AfterUnion=*/false,1695 /*AfterExternBlock=*/false,1696 /*BeforeCatch=*/false,1697 /*BeforeElse=*/false,1698 /*BeforeLambdaBody=*/false,1699 /*BeforeWhile=*/false,1700 /*IndentBraces=*/false,1701 /*SplitEmptyFunction=*/true,1702 /*SplitEmptyRecord=*/true,1703 /*SplitEmptyNamespace=*/true};1704 LLVMStyle.BreakAdjacentStringLiterals = true;1705 LLVMStyle.BreakAfterAttributes = FormatStyle::ABS_Leave;1706 LLVMStyle.BreakAfterJavaFieldAnnotations = false;1707 LLVMStyle.BreakAfterOpenBracketBracedList = false;1708 LLVMStyle.BreakAfterOpenBracketFunction = false;1709 LLVMStyle.BreakAfterOpenBracketIf = false;1710 LLVMStyle.BreakAfterOpenBracketLoop = false;1711 LLVMStyle.BreakAfterOpenBracketSwitch = false;1712 LLVMStyle.BreakAfterReturnType = FormatStyle::RTBS_None;1713 LLVMStyle.BreakArrays = true;1714 LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None;1715 LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;1716 LLVMStyle.BreakBeforeCloseBracketBracedList = false;1717 LLVMStyle.BreakBeforeCloseBracketFunction = false;1718 LLVMStyle.BreakBeforeCloseBracketIf = false;1719 LLVMStyle.BreakBeforeCloseBracketLoop = false;1720 LLVMStyle.BreakBeforeCloseBracketSwitch = false;1721 LLVMStyle.BreakBeforeConceptDeclarations = FormatStyle::BBCDS_Always;1722 LLVMStyle.BreakBeforeInlineASMColon = FormatStyle::BBIAS_OnlyMultiline;1723 LLVMStyle.BreakBeforeTemplateCloser = false;1724 LLVMStyle.BreakBeforeTernaryOperators = true;1725 LLVMStyle.BreakBinaryOperations = FormatStyle::BBO_Never;1726 LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;1727 LLVMStyle.BreakFunctionDefinitionParameters = false;1728 LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;1729 LLVMStyle.BreakStringLiterals = true;1730 LLVMStyle.BreakTemplateDeclarations = FormatStyle::BTDS_MultiLine;1731 LLVMStyle.ColumnLimit = 80;1732 LLVMStyle.CommentPragmas = "^ IWYU pragma:";1733 LLVMStyle.CompactNamespaces = false;1734 LLVMStyle.ConstructorInitializerIndentWidth = 4;1735 LLVMStyle.ContinuationIndentWidth = 4;1736 LLVMStyle.Cpp11BracedListStyle = FormatStyle::BLS_AlignFirstComment;1737 LLVMStyle.DerivePointerAlignment = false;1738 LLVMStyle.DisableFormat = false;1739 LLVMStyle.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Never;1740 LLVMStyle.EmptyLineBeforeAccessModifier = FormatStyle::ELBAMS_LogicalBlock;1741 LLVMStyle.EnumTrailingComma = FormatStyle::ETC_Leave;1742 LLVMStyle.ExperimentalAutoDetectBinPacking = false;1743 LLVMStyle.FixNamespaceComments = true;1744 LLVMStyle.ForEachMacros.push_back("foreach");1745 LLVMStyle.ForEachMacros.push_back("Q_FOREACH");1746 LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH");1747 LLVMStyle.IfMacros.push_back("KJ_IF_MAYBE");1748 LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve;1749 LLVMStyle.IncludeStyle.IncludeCategories = {1750 {"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0, false},1751 {"^(<|\"(gtest|gmock|isl|json)/)", 3, 0, false},1752 {".*", 1, 0, false}};1753 LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$";1754 LLVMStyle.IncludeStyle.MainIncludeChar = tooling::IncludeStyle::MICD_Quote;1755 LLVMStyle.IndentAccessModifiers = false;1756 LLVMStyle.IndentCaseBlocks = false;1757 LLVMStyle.IndentCaseLabels = false;1758 LLVMStyle.IndentExportBlock = true;1759 LLVMStyle.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;1760 LLVMStyle.IndentGotoLabels = true;1761 LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None;1762 LLVMStyle.IndentRequiresClause = true;1763 LLVMStyle.IndentWidth = 2;1764 LLVMStyle.IndentWrappedFunctionNames = false;1765 LLVMStyle.InheritsParentConfig = false;1766 LLVMStyle.InsertBraces = false;1767 LLVMStyle.InsertNewlineAtEOF = false;1768 LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None;1769 LLVMStyle.IntegerLiteralSeparator = {};1770 LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;1771 LLVMStyle.JavaScriptWrapImports = true;1772 LLVMStyle.KeepEmptyLines = {1773 /*AtEndOfFile=*/false,1774 /*AtStartOfBlock=*/true,1775 /*AtStartOfFile=*/true,1776 };1777 LLVMStyle.KeepFormFeed = false;1778 LLVMStyle.LambdaBodyIndentation = FormatStyle::LBI_Signature;1779 LLVMStyle.Language = Language;1780 LLVMStyle.LineEnding = FormatStyle::LE_DeriveLF;1781 LLVMStyle.MaxEmptyLinesToKeep = 1;1782 LLVMStyle.NamespaceIndentation = FormatStyle::NI_None;1783 LLVMStyle.NumericLiteralCase = {/*ExponentLetter=*/FormatStyle::NLCS_Leave,1784 /*HexDigit=*/FormatStyle::NLCS_Leave,1785 /*Prefix=*/FormatStyle::NLCS_Leave,1786 /*Suffix=*/FormatStyle::NLCS_Leave};1787 LLVMStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Auto;1788 LLVMStyle.ObjCBlockIndentWidth = 2;1789 LLVMStyle.ObjCBreakBeforeNestedBlockParam = true;1790 LLVMStyle.ObjCSpaceAfterProperty = false;1791 LLVMStyle.ObjCSpaceBeforeProtocolList = true;1792 LLVMStyle.PackConstructorInitializers = FormatStyle::PCIS_BinPack;1793 LLVMStyle.PointerAlignment = FormatStyle::PAS_Right;1794 LLVMStyle.PPIndentWidth = -1;1795 LLVMStyle.QualifierAlignment = FormatStyle::QAS_Leave;1796 LLVMStyle.ReferenceAlignment = FormatStyle::RAS_Pointer;1797 LLVMStyle.ReflowComments = FormatStyle::RCS_Always;1798 LLVMStyle.RemoveBracesLLVM = false;1799 LLVMStyle.RemoveEmptyLinesInUnwrappedLines = false;1800 LLVMStyle.RemoveParentheses = FormatStyle::RPS_Leave;1801 LLVMStyle.RemoveSemicolon = false;1802 LLVMStyle.RequiresClausePosition = FormatStyle::RCPS_OwnLine;1803 LLVMStyle.RequiresExpressionIndentation = FormatStyle::REI_OuterScope;1804 LLVMStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Leave;1805 LLVMStyle.ShortNamespaceLines = 1;1806 LLVMStyle.SkipMacroDefinitionBody = false;1807 LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false,1808 /*IgnoreExtension=*/false};1809 LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before;1810 LLVMStyle.SortUsingDeclarations = FormatStyle::SUD_LexicographicNumeric;1811 LLVMStyle.SpaceAfterCStyleCast = false;1812 LLVMStyle.SpaceAfterLogicalNot = false;1813 LLVMStyle.SpaceAfterOperatorKeyword = false;1814 LLVMStyle.SpaceAfterTemplateKeyword = true;1815 LLVMStyle.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Default;1816 LLVMStyle.SpaceBeforeAssignmentOperators = true;1817 LLVMStyle.SpaceBeforeCaseColon = false;1818 LLVMStyle.SpaceBeforeCpp11BracedList = false;1819 LLVMStyle.SpaceBeforeCtorInitializerColon = true;1820 LLVMStyle.SpaceBeforeInheritanceColon = true;1821 LLVMStyle.SpaceBeforeJsonColon = false;1822 LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;1823 LLVMStyle.SpaceBeforeParensOptions = {};1824 LLVMStyle.SpaceBeforeParensOptions.AfterControlStatements = true;1825 LLVMStyle.SpaceBeforeParensOptions.AfterForeachMacros = true;1826 LLVMStyle.SpaceBeforeParensOptions.AfterIfMacros = true;1827 LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true;1828 LLVMStyle.SpaceBeforeSquareBrackets = false;1829 LLVMStyle.SpaceInEmptyBraces = FormatStyle::SIEB_Never;1830 LLVMStyle.SpacesBeforeTrailingComments = 1;1831 LLVMStyle.SpacesInAngles = FormatStyle::SIAS_Never;1832 LLVMStyle.SpacesInContainerLiterals = true;1833 LLVMStyle.SpacesInLineCommentPrefix = {1834 /*Minimum=*/1, /*Maximum=*/std::numeric_limits<unsigned>::max()};1835 LLVMStyle.SpacesInParens = FormatStyle::SIPO_Never;1836 LLVMStyle.SpacesInSquareBrackets = false;1837 LLVMStyle.Standard = FormatStyle::LS_Latest;1838 LLVMStyle.StatementAttributeLikeMacros.push_back("Q_EMIT");1839 LLVMStyle.StatementMacros.push_back("Q_UNUSED");1840 LLVMStyle.StatementMacros.push_back("QT_REQUIRE_VERSION");1841 LLVMStyle.TableGenBreakingDAGArgOperators = {};1842 LLVMStyle.TableGenBreakInsideDAGArg = FormatStyle::DAS_DontBreak;1843 LLVMStyle.TabWidth = 8;1844 LLVMStyle.UseTab = FormatStyle::UT_Never;1845 LLVMStyle.VerilogBreakBetweenInstancePorts = true;1846 LLVMStyle.WhitespaceSensitiveMacros.push_back("BOOST_PP_STRINGIZE");1847 LLVMStyle.WhitespaceSensitiveMacros.push_back("CF_SWIFT_NAME");1848 LLVMStyle.WhitespaceSensitiveMacros.push_back("NS_SWIFT_NAME");1849 LLVMStyle.WhitespaceSensitiveMacros.push_back("PP_STRINGIZE");1850 LLVMStyle.WhitespaceSensitiveMacros.push_back("STRINGIZE");1851 LLVMStyle.WrapNamespaceBodyWithEmptyLines = FormatStyle::WNBWELS_Leave;1852 1853 LLVMStyle.PenaltyBreakAssignment = prec::Assignment;1854 LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19;1855 LLVMStyle.PenaltyBreakBeforeMemberAccess = 150;1856 LLVMStyle.PenaltyBreakComment = 300;1857 LLVMStyle.PenaltyBreakFirstLessLess = 120;1858 LLVMStyle.PenaltyBreakOpenParenthesis = 0;1859 LLVMStyle.PenaltyBreakScopeResolution = 500;1860 LLVMStyle.PenaltyBreakString = 1000;1861 LLVMStyle.PenaltyBreakTemplateDeclaration = prec::Relational;1862 LLVMStyle.PenaltyExcessCharacter = 1'000'000;1863 LLVMStyle.PenaltyIndentedWhitespace = 0;1864 LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60;1865 1866 // Defaults that differ when not C++.1867 switch (Language) {1868 case FormatStyle::LK_TableGen:1869 LLVMStyle.SpacesInContainerLiterals = false;1870 break;1871 case FormatStyle::LK_Json:1872 LLVMStyle.ColumnLimit = 0;1873 break;1874 case FormatStyle::LK_Verilog:1875 LLVMStyle.IndentCaseLabels = true;1876 LLVMStyle.SpacesInContainerLiterals = false;1877 break;1878 default:1879 break;1880 }1881 1882 return LLVMStyle;1883}1884 1885FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {1886 if (Language == FormatStyle::LK_TextProto) {1887 FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_Proto);1888 GoogleStyle.Language = FormatStyle::LK_TextProto;1889 1890 return GoogleStyle;1891 }1892 1893 FormatStyle GoogleStyle = getLLVMStyle(Language);1894 1895 GoogleStyle.AccessModifierOffset = -1;1896 GoogleStyle.AlignEscapedNewlines = FormatStyle::ENAS_Left;1897 GoogleStyle.AllowShortIfStatementsOnASingleLine =1898 FormatStyle::SIS_WithoutElse;1899 GoogleStyle.AllowShortLoopsOnASingleLine = true;1900 GoogleStyle.AlwaysBreakBeforeMultilineStrings = true;1901 // Abseil aliases to clang's `_Nonnull`, `_Nullable` and `_Null_unspecified`.1902 GoogleStyle.AttributeMacros.push_back("absl_nonnull");1903 GoogleStyle.AttributeMacros.push_back("absl_nullable");1904 GoogleStyle.AttributeMacros.push_back("absl_nullability_unknown");1905 GoogleStyle.BreakTemplateDeclarations = FormatStyle::BTDS_Yes;1906 GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;1907 GoogleStyle.IncludeStyle.IncludeCategories = {{"^<ext/.*\\.h>", 2, 0, false},1908 {"^<.*\\.h>", 1, 0, false},1909 {"^<.*", 2, 0, false},1910 {".*", 3, 0, false}};1911 GoogleStyle.IncludeStyle.IncludeIsMainRegex = "([-_](test|unittest))?$";1912 GoogleStyle.IndentCaseLabels = true;1913 GoogleStyle.KeepEmptyLines.AtStartOfBlock = false;1914 GoogleStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Never;1915 GoogleStyle.ObjCSpaceAfterProperty = false;1916 GoogleStyle.ObjCSpaceBeforeProtocolList = true;1917 GoogleStyle.PackConstructorInitializers = FormatStyle::PCIS_NextLine;1918 GoogleStyle.PointerAlignment = FormatStyle::PAS_Left;1919 GoogleStyle.RawStringFormats = {1920 {1921 FormatStyle::LK_Cpp,1922 /*Delimiters=*/1923 {1924 "cc",1925 "CC",1926 "cpp",1927 "Cpp",1928 "CPP",1929 "c++",1930 "C++",1931 },1932 /*EnclosingFunctionNames=*/1933 {},1934 /*CanonicalDelimiter=*/"",1935 /*BasedOnStyle=*/"google",1936 },1937 {1938 FormatStyle::LK_TextProto,1939 /*Delimiters=*/1940 {1941 "pb",1942 "PB",1943 "proto",1944 "PROTO",1945 },1946 /*EnclosingFunctionNames=*/1947 {1948 "EqualsProto",1949 "EquivToProto",1950 "PARSE_PARTIAL_TEXT_PROTO",1951 "PARSE_TEST_PROTO",1952 "PARSE_TEXT_PROTO",1953 "ParseTextOrDie",1954 "ParseTextProtoOrDie",1955 "ParseTestProto",1956 "ParsePartialTestProto",1957 },1958 /*CanonicalDelimiter=*/"pb",1959 /*BasedOnStyle=*/"google",1960 },1961 };1962 1963 GoogleStyle.SpacesBeforeTrailingComments = 2;1964 GoogleStyle.Standard = FormatStyle::LS_Auto;1965 1966 GoogleStyle.PenaltyBreakBeforeFirstCallParameter = 1;1967 GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200;1968 1969 if (Language == FormatStyle::LK_Java) {1970 GoogleStyle.AlignAfterOpenBracket = false;1971 GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;1972 GoogleStyle.AlignTrailingComments = {};1973 GoogleStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Never;1974 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;1975 GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;1976 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;1977 GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment;1978 GoogleStyle.ColumnLimit = 100;1979 GoogleStyle.SpaceAfterCStyleCast = true;1980 GoogleStyle.SpacesBeforeTrailingComments = 1;1981 } else if (Language == FormatStyle::LK_JavaScript) {1982 GoogleStyle.BreakAfterOpenBracketBracedList = true;1983 GoogleStyle.BreakAfterOpenBracketFunction = true;1984 GoogleStyle.BreakAfterOpenBracketIf = true;1985 GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;1986 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;1987 // TODO: still under discussion whether to switch to SLS_All.1988 GoogleStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty;1989 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;1990 GoogleStyle.BreakBeforeTernaryOperators = false;1991 // taze:, triple slash directives (`/// <...`), tslint:, and @see, which is1992 // commonly followed by overlong URLs.1993 GoogleStyle.CommentPragmas = "(taze:|^/[ \t]*<|tslint:|@see)";1994 // TODO: enable once decided, in particular re disabling bin packing.1995 // https://google.github.io/styleguide/jsguide.html#features-arrays-trailing-comma1996 // GoogleStyle.InsertTrailingCommas = FormatStyle::TCS_Wrapped;1997 GoogleStyle.JavaScriptQuotes = FormatStyle::JSQS_Single;1998 GoogleStyle.JavaScriptWrapImports = false;1999 GoogleStyle.MaxEmptyLinesToKeep = 3;2000 GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;2001 GoogleStyle.SpacesInContainerLiterals = false;2002 } else if (Language == FormatStyle::LK_Proto) {2003 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;2004 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;2005 // This affects protocol buffer options specifications and text protos.2006 // Text protos are currently mostly formatted inside C++ raw string literals2007 // and often the current breaking behavior of string literals is not2008 // beneficial there. Investigate turning this on once proper string reflow2009 // has been implemented.2010 GoogleStyle.BreakStringLiterals = false;2011 GoogleStyle.Cpp11BracedListStyle = FormatStyle::BLS_Block;2012 GoogleStyle.SpacesInContainerLiterals = false;2013 } else if (Language == FormatStyle::LK_ObjC) {2014 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;2015 GoogleStyle.ColumnLimit = 100;2016 GoogleStyle.DerivePointerAlignment = true;2017 // "Regroup" doesn't work well for ObjC yet (main header heuristic,2018 // relationship between ObjC standard library headers and other heades,2019 // #imports, etc.)2020 GoogleStyle.IncludeStyle.IncludeBlocks =2021 tooling::IncludeStyle::IBS_Preserve;2022 } else if (Language == FormatStyle::LK_CSharp) {2023 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;2024 GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;2025 GoogleStyle.BreakStringLiterals = false;2026 GoogleStyle.ColumnLimit = 100;2027 GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;2028 }2029 2030 return GoogleStyle;2031}2032 2033FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) {2034 FormatStyle ChromiumStyle = getGoogleStyle(Language);2035 2036 // Disable include reordering across blocks in Chromium code.2037 // - clang-format tries to detect that foo.h is the "main" header for2038 // foo.cc and foo_unittest.cc via IncludeIsMainRegex. However, Chromium2039 // uses many other suffices (_win.cc, _mac.mm, _posix.cc, _browsertest.cc,2040 // _private.cc, _impl.cc etc) in different permutations2041 // (_win_browsertest.cc) so disable this until IncludeIsMainRegex has a2042 // better default for Chromium code.2043 // - The default for .cc and .mm files is different (r357695) for Google style2044 // for the same reason. The plan is to unify this again once the main2045 // header detection works for Google's ObjC code, but this hasn't happened2046 // yet. Since Chromium has some ObjC code, switching Chromium is blocked2047 // on that.2048 // - Finally, "If include reordering is harmful, put things in different2049 // blocks to prevent it" has been a recommendation for a long time that2050 // people are used to. We'll need a dev education push to change this to2051 // "If include reordering is harmful, put things in a different block and2052 // _prepend that with a comment_ to prevent it" before changing behavior.2053 ChromiumStyle.IncludeStyle.IncludeBlocks =2054 tooling::IncludeStyle::IBS_Preserve;2055 2056 if (Language == FormatStyle::LK_Java) {2057 ChromiumStyle.AllowShortIfStatementsOnASingleLine =2058 FormatStyle::SIS_WithoutElse;2059 ChromiumStyle.BreakAfterJavaFieldAnnotations = true;2060 ChromiumStyle.ContinuationIndentWidth = 8;2061 ChromiumStyle.IndentWidth = 4;2062 // See styleguide for import groups:2063 // https://chromium.googlesource.com/chromium/src/+/refs/heads/main/styleguide/java/java.md#Import-Order2064 ChromiumStyle.JavaImportGroups = {2065 "android",2066 "androidx",2067 "com",2068 "dalvik",2069 "junit",2070 "org",2071 "com.google.android.apps.chrome",2072 "org.chromium",2073 "java",2074 "javax",2075 };2076 } else if (Language == FormatStyle::LK_JavaScript) {2077 ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;2078 ChromiumStyle.AllowShortLoopsOnASingleLine = false;2079 } else {2080 ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false;2081 ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;2082 ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;2083 ChromiumStyle.AllowShortLoopsOnASingleLine = false;2084 ChromiumStyle.BinPackParameters = FormatStyle::BPPS_OnePerLine;2085 ChromiumStyle.DerivePointerAlignment = false;2086 if (Language == FormatStyle::LK_ObjC)2087 ChromiumStyle.ColumnLimit = 80;2088 }2089 return ChromiumStyle;2090}2091 2092FormatStyle getMozillaStyle() {2093 FormatStyle MozillaStyle = getLLVMStyle();2094 MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false;2095 MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;2096 MozillaStyle.AlwaysBreakAfterDefinitionReturnType =2097 FormatStyle::DRTBS_TopLevel;2098 MozillaStyle.BinPackArguments = false;2099 MozillaStyle.BinPackParameters = FormatStyle::BPPS_OnePerLine;2100 MozillaStyle.BreakAfterReturnType = FormatStyle::RTBS_TopLevel;2101 MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla;2102 MozillaStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;2103 MozillaStyle.BreakInheritanceList = FormatStyle::BILS_BeforeComma;2104 MozillaStyle.BreakTemplateDeclarations = FormatStyle::BTDS_Yes;2105 MozillaStyle.ConstructorInitializerIndentWidth = 2;2106 MozillaStyle.ContinuationIndentWidth = 2;2107 MozillaStyle.Cpp11BracedListStyle = FormatStyle::BLS_Block;2108 MozillaStyle.FixNamespaceComments = false;2109 MozillaStyle.IndentCaseLabels = true;2110 MozillaStyle.ObjCSpaceAfterProperty = true;2111 MozillaStyle.ObjCSpaceBeforeProtocolList = false;2112 MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200;2113 MozillaStyle.PointerAlignment = FormatStyle::PAS_Left;2114 MozillaStyle.SpaceAfterTemplateKeyword = false;2115 return MozillaStyle;2116}2117 2118FormatStyle getWebKitStyle() {2119 FormatStyle Style = getLLVMStyle();2120 Style.AccessModifierOffset = -4;2121 Style.AlignAfterOpenBracket = false;2122 Style.AlignOperands = FormatStyle::OAS_DontAlign;2123 Style.AlignTrailingComments = {};2124 Style.AlignTrailingComments.Kind = FormatStyle::TCAS_Never;2125 Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty;2126 Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;2127 Style.BreakBeforeBraces = FormatStyle::BS_WebKit;2128 Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;2129 Style.ColumnLimit = 0;2130 Style.Cpp11BracedListStyle = FormatStyle::BLS_Block;2131 Style.FixNamespaceComments = false;2132 Style.IndentWidth = 4;2133 Style.NamespaceIndentation = FormatStyle::NI_Inner;2134 Style.ObjCBlockIndentWidth = 4;2135 Style.ObjCSpaceAfterProperty = true;2136 Style.PointerAlignment = FormatStyle::PAS_Left;2137 Style.SpaceBeforeCpp11BracedList = true;2138 Style.SpaceInEmptyBraces = FormatStyle::SIEB_Always;2139 return Style;2140}2141 2142FormatStyle getGNUStyle() {2143 FormatStyle Style = getLLVMStyle();2144 Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All;2145 Style.BreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;2146 Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;2147 Style.BreakBeforeBraces = FormatStyle::BS_GNU;2148 Style.BreakBeforeTernaryOperators = true;2149 Style.ColumnLimit = 79;2150 Style.Cpp11BracedListStyle = FormatStyle::BLS_Block;2151 Style.FixNamespaceComments = false;2152 Style.KeepFormFeed = true;2153 Style.SpaceBeforeParens = FormatStyle::SBPO_Always;2154 return Style;2155}2156 2157FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language) {2158 FormatStyle Style = getLLVMStyle(Language);2159 Style.ColumnLimit = 120;2160 Style.TabWidth = 4;2161 Style.IndentWidth = 4;2162 Style.UseTab = FormatStyle::UT_Never;2163 Style.BreakBeforeBraces = FormatStyle::BS_Custom;2164 Style.BraceWrapping.AfterClass = true;2165 Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;2166 Style.BraceWrapping.AfterEnum = true;2167 Style.BraceWrapping.AfterFunction = true;2168 Style.BraceWrapping.AfterNamespace = true;2169 Style.BraceWrapping.AfterObjCDeclaration = true;2170 Style.BraceWrapping.AfterStruct = true;2171 Style.BraceWrapping.AfterExternBlock = true;2172 Style.BraceWrapping.BeforeCatch = true;2173 Style.BraceWrapping.BeforeElse = true;2174 Style.BraceWrapping.BeforeWhile = false;2175 Style.PenaltyReturnTypeOnItsOwnLine = 1000;2176 Style.AllowShortEnumsOnASingleLine = false;2177 Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;2178 Style.AllowShortCaseLabelsOnASingleLine = false;2179 Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;2180 Style.AllowShortLoopsOnASingleLine = false;2181 Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;2182 Style.BreakAfterReturnType = FormatStyle::RTBS_None;2183 return Style;2184}2185 2186FormatStyle getClangFormatStyle() {2187 FormatStyle Style = getLLVMStyle();2188 Style.InsertBraces = true;2189 Style.InsertNewlineAtEOF = true;2190 Style.IntegerLiteralSeparator.Decimal = 3;2191 Style.IntegerLiteralSeparator.DecimalMinDigitsInsert = 5;2192 Style.LineEnding = FormatStyle::LE_LF;2193 Style.RemoveBracesLLVM = true;2194 Style.RemoveEmptyLinesInUnwrappedLines = true;2195 Style.RemoveParentheses = FormatStyle::RPS_ReturnStatement;2196 Style.RemoveSemicolon = true;2197 return Style;2198}2199 2200FormatStyle getNoStyle() {2201 FormatStyle NoStyle = getLLVMStyle();2202 NoStyle.DisableFormat = true;2203 NoStyle.SortIncludes = {};2204 NoStyle.SortUsingDeclarations = FormatStyle::SUD_Never;2205 return NoStyle;2206}2207 2208bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language,2209 FormatStyle *Style) {2210 if (Name.equals_insensitive("llvm"))2211 *Style = getLLVMStyle(Language);2212 else if (Name.equals_insensitive("chromium"))2213 *Style = getChromiumStyle(Language);2214 else if (Name.equals_insensitive("mozilla"))2215 *Style = getMozillaStyle();2216 else if (Name.equals_insensitive("google"))2217 *Style = getGoogleStyle(Language);2218 else if (Name.equals_insensitive("webkit"))2219 *Style = getWebKitStyle();2220 else if (Name.equals_insensitive("gnu"))2221 *Style = getGNUStyle();2222 else if (Name.equals_insensitive("microsoft"))2223 *Style = getMicrosoftStyle(Language);2224 else if (Name.equals_insensitive("clang-format"))2225 *Style = getClangFormatStyle();2226 else if (Name.equals_insensitive("none"))2227 *Style = getNoStyle();2228 else if (Name.equals_insensitive("inheritparentconfig"))2229 Style->InheritsParentConfig = true;2230 else2231 return false;2232 2233 Style->Language = Language;2234 return true;2235}2236 2237ParseError validateQualifierOrder(FormatStyle *Style) {2238 // If its empty then it means don't do anything.2239 if (Style->QualifierOrder.empty())2240 return ParseError::MissingQualifierOrder;2241 2242 // Ensure the list contains only currently valid qualifiers.2243 for (const auto &Qualifier : Style->QualifierOrder) {2244 if (Qualifier == "type")2245 continue;2246 auto token =2247 LeftRightQualifierAlignmentFixer::getTokenFromQualifier(Qualifier);2248 if (token == tok::identifier)2249 return ParseError::InvalidQualifierSpecified;2250 }2251 2252 // Ensure the list is unique (no duplicates).2253 std::set<std::string> UniqueQualifiers(Style->QualifierOrder.begin(),2254 Style->QualifierOrder.end());2255 if (Style->QualifierOrder.size() != UniqueQualifiers.size()) {2256 LLVM_DEBUG(llvm::dbgs()2257 << "Duplicate Qualifiers " << Style->QualifierOrder.size()2258 << " vs " << UniqueQualifiers.size() << "\n");2259 return ParseError::DuplicateQualifierSpecified;2260 }2261 2262 // Ensure the list has 'type' in it.2263 if (!llvm::is_contained(Style->QualifierOrder, "type"))2264 return ParseError::MissingQualifierType;2265 2266 return ParseError::Success;2267}2268 2269std::error_code parseConfiguration(llvm::MemoryBufferRef Config,2270 FormatStyle *Style, bool AllowUnknownOptions,2271 llvm::SourceMgr::DiagHandlerTy DiagHandler,2272 void *DiagHandlerCtxt, bool IsDotHFile) {2273 assert(Style);2274 FormatStyle::LanguageKind Language = Style->Language;2275 assert(Language != FormatStyle::LK_None);2276 if (Config.getBuffer().trim().empty())2277 return make_error_code(ParseError::Success);2278 Style->StyleSet.Clear();2279 std::vector<FormatStyle> Styles;2280 llvm::yaml::Input Input(Config, /*Ctxt=*/nullptr, DiagHandler,2281 DiagHandlerCtxt);2282 // DocumentListTraits<vector<FormatStyle>> uses the context to get default2283 // values for the fields, keys for which are missing from the configuration.2284 // Mapping also uses the context to get the language to find the correct2285 // base style.2286 Input.setContext(Style);2287 Input.setAllowUnknownKeys(AllowUnknownOptions);2288 Input >> Styles;2289 if (Input.error())2290 return Input.error();2291 if (Styles.empty())2292 return make_error_code(ParseError::Success);2293 2294 const auto StyleCount = Styles.size();2295 2296 // Start from the second style as (only) the first one may be the default.2297 for (unsigned I = 1; I < StyleCount; ++I) {2298 const auto Lang = Styles[I].Language;2299 if (Lang == FormatStyle::LK_None)2300 return make_error_code(ParseError::Error);2301 // Ensure that each language is configured at most once.2302 for (unsigned J = 0; J < I; ++J) {2303 if (Lang == Styles[J].Language) {2304 LLVM_DEBUG(llvm::dbgs()2305 << "Duplicate languages in the config file on positions "2306 << J << " and " << I << '\n');2307 return make_error_code(ParseError::Error);2308 }2309 }2310 }2311 2312 int LanguagePos = -1; // Position of the style for Language.2313 int CppPos = -1; // Position of the style for C++.2314 int CPos = -1; // Position of the style for C.2315 2316 // Search Styles for Language and store the positions of C++ and C styles in2317 // case Language is not found.2318 for (unsigned I = 0; I < StyleCount; ++I) {2319 const auto Lang = Styles[I].Language;2320 if (Lang == Language) {2321 LanguagePos = I;2322 break;2323 }2324 if (Lang == FormatStyle::LK_Cpp)2325 CppPos = I;2326 else if (Lang == FormatStyle::LK_C)2327 CPos = I;2328 }2329 2330 // If Language is not found, use the default style if there is one. Otherwise,2331 // use the C style for C++ .h files and for backward compatibility, the C++2332 // style for .c files.2333 if (LanguagePos < 0) {2334 if (Styles[0].Language == FormatStyle::LK_None) // Default style.2335 LanguagePos = 0;2336 else if (IsDotHFile && Language == FormatStyle::LK_Cpp)2337 LanguagePos = CPos;2338 else if (!IsDotHFile && Language == FormatStyle::LK_C)2339 LanguagePos = CppPos;2340 if (LanguagePos < 0)2341 return make_error_code(ParseError::Unsuitable);2342 }2343 2344 for (const auto &S : llvm::reverse(llvm::drop_begin(Styles)))2345 Style->StyleSet.Add(S);2346 2347 *Style = Styles[LanguagePos];2348 2349 if (LanguagePos == 0) {2350 if (Style->Language == FormatStyle::LK_None) // Default style.2351 Style->Language = Language;2352 Style->StyleSet.Add(*Style);2353 }2354 2355 if (Style->InsertTrailingCommas != FormatStyle::TCS_None &&2356 Style->BinPackArguments) {2357 // See comment on FormatStyle::TSC_Wrapped.2358 return make_error_code(ParseError::BinPackTrailingCommaConflict);2359 }2360 if (Style->QualifierAlignment != FormatStyle::QAS_Leave)2361 return make_error_code(validateQualifierOrder(Style));2362 return make_error_code(ParseError::Success);2363}2364 2365std::string configurationAsText(const FormatStyle &Style) {2366 std::string Text;2367 llvm::raw_string_ostream Stream(Text);2368 llvm::yaml::Output Output(Stream);2369 // We use the same mapping method for input and output, so we need a non-const2370 // reference here.2371 FormatStyle NonConstStyle = Style;2372 expandPresetsBraceWrapping(NonConstStyle);2373 expandPresetsSpaceBeforeParens(NonConstStyle);2374 expandPresetsSpacesInParens(NonConstStyle);2375 Output << NonConstStyle;2376 2377 return Stream.str();2378}2379 2380std::optional<FormatStyle>2381FormatStyle::FormatStyleSet::Get(FormatStyle::LanguageKind Language) const {2382 if (!Styles)2383 return std::nullopt;2384 auto It = Styles->find(Language);2385 if (It == Styles->end())2386 return std::nullopt;2387 FormatStyle Style = It->second;2388 Style.StyleSet = *this;2389 return Style;2390}2391 2392void FormatStyle::FormatStyleSet::Add(FormatStyle Style) {2393 assert(Style.Language != LK_None &&2394 "Cannot add a style for LK_None to a StyleSet");2395 assert(2396 !Style.StyleSet.Styles &&2397 "Cannot add a style associated with an existing StyleSet to a StyleSet");2398 if (!Styles)2399 Styles = std::make_shared<MapType>();2400 (*Styles)[Style.Language] = std::move(Style);2401}2402 2403void FormatStyle::FormatStyleSet::Clear() { Styles.reset(); }2404 2405std::optional<FormatStyle>2406FormatStyle::GetLanguageStyle(FormatStyle::LanguageKind Language) const {2407 return StyleSet.Get(Language);2408}2409 2410namespace {2411 2412void replaceToken(const FormatToken &Token, FormatToken *Next,2413 const SourceManager &SourceMgr, tooling::Replacements &Result,2414 StringRef Text = "") {2415 const auto &Tok = Token.Tok;2416 SourceLocation Start;2417 if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) {2418 Start = Tok.getLocation();2419 Next->WhitespaceRange = Token.WhitespaceRange;2420 } else {2421 Start = Token.WhitespaceRange.getBegin();2422 }2423 const auto &Range = CharSourceRange::getCharRange(Start, Tok.getEndLoc());2424 cantFail(Result.add(tooling::Replacement(SourceMgr, Range, Text)));2425}2426 2427class ParensRemover : public TokenAnalyzer {2428public:2429 ParensRemover(const Environment &Env, const FormatStyle &Style)2430 : TokenAnalyzer(Env, Style) {}2431 2432 std::pair<tooling::Replacements, unsigned>2433 analyze(TokenAnnotator &Annotator,2434 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,2435 FormatTokenLexer &Tokens) override {2436 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);2437 tooling::Replacements Result;2438 removeParens(AnnotatedLines, Result);2439 return {Result, 0};2440 }2441 2442private:2443 void removeParens(SmallVectorImpl<AnnotatedLine *> &Lines,2444 tooling::Replacements &Result) {2445 const auto &SourceMgr = Env.getSourceManager();2446 for (auto *Line : Lines) {2447 if (!Line->Children.empty())2448 removeParens(Line->Children, Result);2449 if (!Line->Affected)2450 continue;2451 for (const auto *Token = Line->First; Token && !Token->Finalized;2452 Token = Token->Next) {2453 if (Token->Optional && Token->isOneOf(tok::l_paren, tok::r_paren))2454 replaceToken(*Token, Token->Next, SourceMgr, Result, " ");2455 }2456 }2457 }2458};2459 2460class BracesInserter : public TokenAnalyzer {2461public:2462 BracesInserter(const Environment &Env, const FormatStyle &Style)2463 : TokenAnalyzer(Env, Style) {}2464 2465 std::pair<tooling::Replacements, unsigned>2466 analyze(TokenAnnotator &Annotator,2467 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,2468 FormatTokenLexer &Tokens) override {2469 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);2470 tooling::Replacements Result;2471 insertBraces(AnnotatedLines, Result);2472 return {Result, 0};2473 }2474 2475private:2476 void insertBraces(SmallVectorImpl<AnnotatedLine *> &Lines,2477 tooling::Replacements &Result) {2478 const auto &SourceMgr = Env.getSourceManager();2479 int OpeningBraceSurplus = 0;2480 for (AnnotatedLine *Line : Lines) {2481 if (!Line->Children.empty())2482 insertBraces(Line->Children, Result);2483 if (!Line->Affected && OpeningBraceSurplus == 0)2484 continue;2485 for (FormatToken *Token = Line->First; Token && !Token->Finalized;2486 Token = Token->Next) {2487 int BraceCount = Token->BraceCount;2488 if (BraceCount == 0)2489 continue;2490 std::string Brace;2491 if (BraceCount < 0) {2492 assert(BraceCount == -1);2493 if (!Line->Affected)2494 break;2495 Brace = Token->is(tok::comment) ? "\n{" : "{";2496 ++OpeningBraceSurplus;2497 } else {2498 if (OpeningBraceSurplus == 0)2499 break;2500 if (OpeningBraceSurplus < BraceCount)2501 BraceCount = OpeningBraceSurplus;2502 Brace = '\n' + std::string(BraceCount, '}');2503 OpeningBraceSurplus -= BraceCount;2504 }2505 Token->BraceCount = 0;2506 const auto Start = Token->Tok.getEndLoc();2507 cantFail(Result.add(tooling::Replacement(SourceMgr, Start, 0, Brace)));2508 }2509 }2510 assert(OpeningBraceSurplus == 0);2511 }2512};2513 2514class BracesRemover : public TokenAnalyzer {2515public:2516 BracesRemover(const Environment &Env, const FormatStyle &Style)2517 : TokenAnalyzer(Env, Style) {}2518 2519 std::pair<tooling::Replacements, unsigned>2520 analyze(TokenAnnotator &Annotator,2521 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,2522 FormatTokenLexer &Tokens) override {2523 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);2524 tooling::Replacements Result;2525 removeBraces(AnnotatedLines, Result);2526 return {Result, 0};2527 }2528 2529private:2530 void removeBraces(SmallVectorImpl<AnnotatedLine *> &Lines,2531 tooling::Replacements &Result) {2532 const auto &SourceMgr = Env.getSourceManager();2533 const auto *End = Lines.end();2534 for (const auto *I = Lines.begin(); I != End; ++I) {2535 const auto &Line = *I;2536 if (!Line->Children.empty())2537 removeBraces(Line->Children, Result);2538 if (!Line->Affected)2539 continue;2540 const auto *NextLine = I + 1 == End ? nullptr : I[1];2541 for (const auto *Token = Line->First; Token && !Token->Finalized;2542 Token = Token->Next) {2543 if (!Token->Optional || Token->isNoneOf(tok::l_brace, tok::r_brace))2544 continue;2545 auto *Next = Token->Next;2546 assert(Next || Token == Line->Last);2547 if (!Next && NextLine)2548 Next = NextLine->First;2549 replaceToken(*Token, Next, SourceMgr, Result);2550 }2551 }2552 }2553};2554 2555class SemiRemover : public TokenAnalyzer {2556public:2557 SemiRemover(const Environment &Env, const FormatStyle &Style)2558 : TokenAnalyzer(Env, Style) {}2559 2560 std::pair<tooling::Replacements, unsigned>2561 analyze(TokenAnnotator &Annotator,2562 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,2563 FormatTokenLexer &Tokens) override {2564 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);2565 tooling::Replacements Result;2566 removeSemi(Annotator, AnnotatedLines, Result);2567 return {Result, 0};2568 }2569 2570private:2571 void removeSemi(TokenAnnotator &Annotator,2572 SmallVectorImpl<AnnotatedLine *> &Lines,2573 tooling::Replacements &Result) {2574 auto PrecededByFunctionRBrace = [](const FormatToken &Tok) {2575 const auto *Prev = Tok.Previous;2576 if (!Prev || Prev->isNot(tok::r_brace))2577 return false;2578 const auto *LBrace = Prev->MatchingParen;2579 return LBrace && LBrace->is(TT_FunctionLBrace);2580 };2581 const auto &SourceMgr = Env.getSourceManager();2582 const auto *End = Lines.end();2583 for (const auto *I = Lines.begin(); I != End; ++I) {2584 const auto &Line = *I;2585 if (!Line->Children.empty())2586 removeSemi(Annotator, Line->Children, Result);2587 if (!Line->Affected)2588 continue;2589 Annotator.calculateFormattingInformation(*Line);2590 const auto *NextLine = I + 1 == End ? nullptr : I[1];2591 for (const auto *Token = Line->First; Token && !Token->Finalized;2592 Token = Token->Next) {2593 if (Token->isNot(tok::semi) ||2594 (!Token->Optional && !PrecededByFunctionRBrace(*Token))) {2595 continue;2596 }2597 auto *Next = Token->Next;2598 assert(Next || Token == Line->Last);2599 if (!Next && NextLine)2600 Next = NextLine->First;2601 replaceToken(*Token, Next, SourceMgr, Result);2602 }2603 }2604 }2605};2606 2607class EnumTrailingCommaEditor : public TokenAnalyzer {2608public:2609 EnumTrailingCommaEditor(const Environment &Env, const FormatStyle &Style)2610 : TokenAnalyzer(Env, Style) {}2611 2612 std::pair<tooling::Replacements, unsigned>2613 analyze(TokenAnnotator &Annotator,2614 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,2615 FormatTokenLexer &Tokens) override {2616 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);2617 tooling::Replacements Result;2618 editEnumTrailingComma(AnnotatedLines, Result);2619 return {Result, 0};2620 }2621 2622private:2623 void editEnumTrailingComma(SmallVectorImpl<AnnotatedLine *> &Lines,2624 tooling::Replacements &Result) {2625 bool InEnumBraces = false;2626 const FormatToken *BeforeRBrace = nullptr;2627 const auto &SourceMgr = Env.getSourceManager();2628 for (auto *Line : Lines) {2629 if (!Line->Children.empty())2630 editEnumTrailingComma(Line->Children, Result);2631 for (const auto *Token = Line->First; Token && !Token->Finalized;2632 Token = Token->Next) {2633 if (Token->isNot(TT_EnumRBrace)) {2634 if (Token->is(TT_EnumLBrace))2635 InEnumBraces = true;2636 else if (InEnumBraces && Token->isNot(tok::comment))2637 BeforeRBrace = Line->Affected ? Token : nullptr;2638 continue;2639 }2640 InEnumBraces = false;2641 if (!BeforeRBrace) // Empty braces or Line not affected.2642 continue;2643 if (BeforeRBrace->is(tok::comma)) {2644 if (Style.EnumTrailingComma == FormatStyle::ETC_Remove)2645 replaceToken(*BeforeRBrace, BeforeRBrace->Next, SourceMgr, Result);2646 } else if (Style.EnumTrailingComma == FormatStyle::ETC_Insert) {2647 cantFail(Result.add(tooling::Replacement(2648 SourceMgr, BeforeRBrace->Tok.getEndLoc(), 0, ",")));2649 }2650 BeforeRBrace = nullptr;2651 }2652 }2653 }2654};2655 2656class JavaScriptRequoter : public TokenAnalyzer {2657public:2658 JavaScriptRequoter(const Environment &Env, const FormatStyle &Style)2659 : TokenAnalyzer(Env, Style) {}2660 2661 std::pair<tooling::Replacements, unsigned>2662 analyze(TokenAnnotator &Annotator,2663 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,2664 FormatTokenLexer &Tokens) override {2665 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);2666 tooling::Replacements Result;2667 requoteJSStringLiteral(AnnotatedLines, Result);2668 return {Result, 0};2669 }2670 2671private:2672 // Replaces double/single-quoted string literal as appropriate, re-escaping2673 // the contents in the process.2674 void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines,2675 tooling::Replacements &Result) {2676 for (AnnotatedLine *Line : Lines) {2677 requoteJSStringLiteral(Line->Children, Result);2678 if (!Line->Affected)2679 continue;2680 for (FormatToken *FormatTok = Line->First; FormatTok;2681 FormatTok = FormatTok->Next) {2682 StringRef Input = FormatTok->TokenText;2683 if (FormatTok->Finalized || !FormatTok->isStringLiteral() ||2684 // NB: testing for not starting with a double quote to avoid2685 // breaking `template strings`.2686 (Style.JavaScriptQuotes == FormatStyle::JSQS_Single &&2687 !Input.starts_with("\"")) ||2688 (Style.JavaScriptQuotes == FormatStyle::JSQS_Double &&2689 !Input.starts_with("\'"))) {2690 continue;2691 }2692 2693 // Change start and end quote.2694 bool IsSingle = Style.JavaScriptQuotes == FormatStyle::JSQS_Single;2695 SourceLocation Start = FormatTok->Tok.getLocation();2696 auto Replace = [&](SourceLocation Start, unsigned Length,2697 StringRef ReplacementText) {2698 auto Err = Result.add(tooling::Replacement(2699 Env.getSourceManager(), Start, Length, ReplacementText));2700 // FIXME: handle error. For now, print error message and skip the2701 // replacement for release version.2702 if (Err) {2703 llvm::errs() << toString(std::move(Err)) << "\n";2704 assert(false);2705 }2706 };2707 Replace(Start, 1, IsSingle ? "'" : "\"");2708 Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1,2709 IsSingle ? "'" : "\"");2710 2711 // Escape internal quotes.2712 bool Escaped = false;2713 for (size_t i = 1; i < Input.size() - 1; i++) {2714 switch (Input[i]) {2715 case '\\':2716 if (!Escaped && i + 1 < Input.size() &&2717 ((IsSingle && Input[i + 1] == '"') ||2718 (!IsSingle && Input[i + 1] == '\''))) {2719 // Remove this \, it's escaping a " or ' that no longer needs2720 // escaping2721 Replace(Start.getLocWithOffset(i), 1, "");2722 continue;2723 }2724 Escaped = !Escaped;2725 break;2726 case '\"':2727 case '\'':2728 if (!Escaped && IsSingle == (Input[i] == '\'')) {2729 // Escape the quote.2730 Replace(Start.getLocWithOffset(i), 0, "\\");2731 }2732 Escaped = false;2733 break;2734 default:2735 Escaped = false;2736 break;2737 }2738 }2739 }2740 }2741 }2742};2743 2744class Formatter : public TokenAnalyzer {2745public:2746 Formatter(const Environment &Env, const FormatStyle &Style,2747 FormattingAttemptStatus *Status)2748 : TokenAnalyzer(Env, Style), Status(Status) {}2749 2750 std::pair<tooling::Replacements, unsigned>2751 analyze(TokenAnnotator &Annotator,2752 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,2753 FormatTokenLexer &Tokens) override {2754 tooling::Replacements Result;2755 deriveLocalStyle(AnnotatedLines);2756 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);2757 for (AnnotatedLine *Line : AnnotatedLines)2758 Annotator.calculateFormattingInformation(*Line);2759 Annotator.setCommentLineLevels(AnnotatedLines);2760 2761 WhitespaceManager Whitespaces(2762 Env.getSourceManager(), Style,2763 Style.LineEnding > FormatStyle::LE_CRLF2764 ? WhitespaceManager::inputUsesCRLF(2765 Env.getSourceManager().getBufferData(Env.getFileID()),2766 Style.LineEnding == FormatStyle::LE_DeriveCRLF)2767 : Style.LineEnding == FormatStyle::LE_CRLF);2768 ContinuationIndenter Indenter(Style, Tokens.getKeywords(),2769 Env.getSourceManager(), Whitespaces, Encoding,2770 BinPackInconclusiveFunctions);2771 unsigned Penalty =2772 UnwrappedLineFormatter(&Indenter, &Whitespaces, Style,2773 Tokens.getKeywords(), Env.getSourceManager(),2774 Status)2775 .format(AnnotatedLines, /*DryRun=*/false,2776 /*AdditionalIndent=*/0,2777 /*FixBadIndentation=*/false,2778 /*FirstStartColumn=*/Env.getFirstStartColumn(),2779 /*NextStartColumn=*/Env.getNextStartColumn(),2780 /*LastStartColumn=*/Env.getLastStartColumn());2781 for (const auto &R : Whitespaces.generateReplacements())2782 if (Result.add(R))2783 return std::make_pair(Result, 0);2784 return std::make_pair(Result, Penalty);2785 }2786 2787private:2788 bool2789 hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine *> &Lines) {2790 for (const AnnotatedLine *Line : Lines) {2791 if (hasCpp03IncompatibleFormat(Line->Children))2792 return true;2793 for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) {2794 if (!Tok->hasWhitespaceBefore()) {2795 if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener))2796 return true;2797 if (Tok->is(TT_TemplateCloser) &&2798 Tok->Previous->is(TT_TemplateCloser)) {2799 return true;2800 }2801 }2802 }2803 }2804 return false;2805 }2806 2807 int countVariableAlignments(const SmallVectorImpl<AnnotatedLine *> &Lines) {2808 int AlignmentDiff = 0;2809 2810 for (const AnnotatedLine *Line : Lines) {2811 AlignmentDiff += countVariableAlignments(Line->Children);2812 2813 for (const auto *Tok = Line->getFirstNonComment(); Tok; Tok = Tok->Next) {2814 if (Tok->isNot(TT_PointerOrReference))2815 continue;2816 2817 const auto *Prev = Tok->Previous;2818 const bool PrecededByName = Prev && Prev->Tok.getIdentifierInfo();2819 const bool SpaceBefore = Tok->hasWhitespaceBefore();2820 2821 // e.g. `int **`, `int*&`, etc.2822 while (Tok->Next && Tok->Next->is(TT_PointerOrReference))2823 Tok = Tok->Next;2824 2825 const auto *Next = Tok->Next;2826 const bool FollowedByName = Next && Next->Tok.getIdentifierInfo();2827 const bool SpaceAfter = Next && Next->hasWhitespaceBefore();2828 2829 if ((!PrecededByName && !FollowedByName) ||2830 // e.g. `int * i` or `int*i`2831 (PrecededByName && FollowedByName && SpaceBefore == SpaceAfter)) {2832 continue;2833 }2834 2835 if ((PrecededByName && SpaceBefore) ||2836 (FollowedByName && !SpaceAfter)) {2837 // Right alignment.2838 ++AlignmentDiff;2839 } else if ((PrecededByName && !SpaceBefore) ||2840 (FollowedByName && SpaceAfter)) {2841 // Left alignment.2842 --AlignmentDiff;2843 }2844 }2845 }2846 2847 return AlignmentDiff;2848 }2849 2850 void2851 deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {2852 bool HasBinPackedFunction = false;2853 bool HasOnePerLineFunction = false;2854 for (AnnotatedLine *Line : AnnotatedLines) {2855 if (!Line->First->Next)2856 continue;2857 FormatToken *Tok = Line->First->Next;2858 while (Tok->Next) {2859 if (Tok->is(PPK_BinPacked))2860 HasBinPackedFunction = true;2861 if (Tok->is(PPK_OnePerLine))2862 HasOnePerLineFunction = true;2863 2864 Tok = Tok->Next;2865 }2866 }2867 if (Style.DerivePointerAlignment) {2868 const auto NetRightCount = countVariableAlignments(AnnotatedLines);2869 if (NetRightCount > 0)2870 Style.PointerAlignment = FormatStyle::PAS_Right;2871 else if (NetRightCount < 0)2872 Style.PointerAlignment = FormatStyle::PAS_Left;2873 Style.ReferenceAlignment = FormatStyle::RAS_Pointer;2874 }2875 if (Style.Standard == FormatStyle::LS_Auto) {2876 Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines)2877 ? FormatStyle::LS_Latest2878 : FormatStyle::LS_Cpp03;2879 }2880 BinPackInconclusiveFunctions =2881 HasBinPackedFunction || !HasOnePerLineFunction;2882 }2883 2884 bool BinPackInconclusiveFunctions;2885 FormattingAttemptStatus *Status;2886};2887 2888/// TrailingCommaInserter inserts trailing commas into container literals.2889/// E.g.:2890/// const x = [2891/// 1,2892/// ];2893/// TrailingCommaInserter runs after formatting. To avoid causing a required2894/// reformatting (and thus reflow), it never inserts a comma that'd exceed the2895/// ColumnLimit.2896///2897/// Because trailing commas disable binpacking of arrays, TrailingCommaInserter2898/// is conceptually incompatible with bin packing.2899class TrailingCommaInserter : public TokenAnalyzer {2900public:2901 TrailingCommaInserter(const Environment &Env, const FormatStyle &Style)2902 : TokenAnalyzer(Env, Style) {}2903 2904 std::pair<tooling::Replacements, unsigned>2905 analyze(TokenAnnotator &Annotator,2906 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,2907 FormatTokenLexer &Tokens) override {2908 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);2909 tooling::Replacements Result;2910 insertTrailingCommas(AnnotatedLines, Result);2911 return {Result, 0};2912 }2913 2914private:2915 /// Inserts trailing commas in [] and {} initializers if they wrap over2916 /// multiple lines.2917 void insertTrailingCommas(SmallVectorImpl<AnnotatedLine *> &Lines,2918 tooling::Replacements &Result) {2919 for (AnnotatedLine *Line : Lines) {2920 insertTrailingCommas(Line->Children, Result);2921 if (!Line->Affected)2922 continue;2923 for (FormatToken *FormatTok = Line->First; FormatTok;2924 FormatTok = FormatTok->Next) {2925 if (FormatTok->NewlinesBefore == 0)2926 continue;2927 FormatToken *Matching = FormatTok->MatchingParen;2928 if (!Matching || !FormatTok->getPreviousNonComment())2929 continue;2930 if (!(FormatTok->is(tok::r_square) &&2931 Matching->is(TT_ArrayInitializerLSquare)) &&2932 !(FormatTok->is(tok::r_brace) && Matching->is(TT_DictLiteral))) {2933 continue;2934 }2935 FormatToken *Prev = FormatTok->getPreviousNonComment();2936 if (Prev->is(tok::comma) || Prev->is(tok::semi))2937 continue;2938 // getEndLoc is not reliably set during re-lexing, use text length2939 // instead.2940 SourceLocation Start =2941 Prev->Tok.getLocation().getLocWithOffset(Prev->TokenText.size());2942 // If inserting a comma would push the code over the column limit, skip2943 // this location - it'd introduce an unstable formatting due to the2944 // required reflow.2945 unsigned ColumnNumber =2946 Env.getSourceManager().getSpellingColumnNumber(Start);2947 if (ColumnNumber > Style.ColumnLimit)2948 continue;2949 // Comma insertions cannot conflict with each other, and this pass has a2950 // clean set of Replacements, so the operation below cannot fail.2951 cantFail(Result.add(2952 tooling::Replacement(Env.getSourceManager(), Start, 0, ",")));2953 }2954 }2955 }2956};2957 2958// This class clean up the erroneous/redundant code around the given ranges in2959// file.2960class Cleaner : public TokenAnalyzer {2961public:2962 Cleaner(const Environment &Env, const FormatStyle &Style)2963 : TokenAnalyzer(Env, Style),2964 DeletedTokens(FormatTokenLess(Env.getSourceManager())) {}2965 2966 // FIXME: eliminate unused parameters.2967 std::pair<tooling::Replacements, unsigned>2968 analyze(TokenAnnotator &Annotator,2969 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,2970 FormatTokenLexer &Tokens) override {2971 // FIXME: in the current implementation the granularity of affected range2972 // is an annotated line. However, this is not sufficient. Furthermore,2973 // redundant code introduced by replacements does not necessarily2974 // intercept with ranges of replacements that result in the redundancy.2975 // To determine if some redundant code is actually introduced by2976 // replacements(e.g. deletions), we need to come up with a more2977 // sophisticated way of computing affected ranges.2978 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);2979 2980 checkEmptyNamespace(AnnotatedLines);2981 2982 for (auto *Line : AnnotatedLines)2983 cleanupLine(Line);2984 2985 return {generateFixes(), 0};2986 }2987 2988private:2989 void cleanupLine(AnnotatedLine *Line) {2990 for (auto *Child : Line->Children)2991 cleanupLine(Child);2992 2993 if (Line->Affected) {2994 cleanupRight(Line->First, tok::comma, tok::comma);2995 cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma);2996 cleanupRight(Line->First, tok::l_paren, tok::comma);2997 cleanupLeft(Line->First, tok::comma, tok::r_paren);2998 cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace);2999 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace);3000 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal);3001 }3002 }3003 3004 bool containsOnlyComments(const AnnotatedLine &Line) {3005 for (FormatToken *Tok = Line.First; Tok; Tok = Tok->Next)3006 if (Tok->isNot(tok::comment))3007 return false;3008 return true;3009 }3010 3011 // Iterate through all lines and remove any empty (nested) namespaces.3012 void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {3013 std::set<unsigned> DeletedLines;3014 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {3015 auto &Line = *AnnotatedLines[i];3016 if (Line.startsWithNamespace())3017 checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines);3018 }3019 3020 for (auto Line : DeletedLines) {3021 FormatToken *Tok = AnnotatedLines[Line]->First;3022 while (Tok) {3023 deleteToken(Tok);3024 Tok = Tok->Next;3025 }3026 }3027 }3028 3029 // The function checks if the namespace, which starts from \p CurrentLine, and3030 // its nested namespaces are empty and delete them if they are empty. It also3031 // sets \p NewLine to the last line checked.3032 // Returns true if the current namespace is empty.3033 bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,3034 unsigned CurrentLine, unsigned &NewLine,3035 std::set<unsigned> &DeletedLines) {3036 unsigned InitLine = CurrentLine, End = AnnotatedLines.size();3037 if (Style.BraceWrapping.AfterNamespace) {3038 // If the left brace is in a new line, we should consume it first so that3039 // it does not make the namespace non-empty.3040 // FIXME: error handling if there is no left brace.3041 if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) {3042 NewLine = CurrentLine;3043 return false;3044 }3045 } else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) {3046 return false;3047 }3048 while (++CurrentLine < End) {3049 if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace))3050 break;3051 3052 if (AnnotatedLines[CurrentLine]->startsWithNamespace()) {3053 if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine,3054 DeletedLines)) {3055 return false;3056 }3057 CurrentLine = NewLine;3058 continue;3059 }3060 3061 if (containsOnlyComments(*AnnotatedLines[CurrentLine]))3062 continue;3063 3064 // If there is anything other than comments or nested namespaces in the3065 // current namespace, the namespace cannot be empty.3066 NewLine = CurrentLine;3067 return false;3068 }3069 3070 NewLine = CurrentLine;3071 if (CurrentLine >= End)3072 return false;3073 3074 // Check if the empty namespace is actually affected by changed ranges.3075 if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange(3076 AnnotatedLines[InitLine]->First->Tok.getLocation(),3077 AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc()))) {3078 return false;3079 }3080 3081 for (unsigned i = InitLine; i <= CurrentLine; ++i)3082 DeletedLines.insert(i);3083 3084 return true;3085 }3086 3087 // Checks pairs {start, start->next},..., {end->previous, end} and deletes one3088 // of the token in the pair if the left token has \p LK token kind and the3089 // right token has \p RK token kind. If \p DeleteLeft is true, the left token3090 // is deleted on match; otherwise, the right token is deleted.3091 template <typename LeftKind, typename RightKind>3092 void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK,3093 bool DeleteLeft) {3094 auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * {3095 for (auto *Res = Tok.Next; Res; Res = Res->Next) {3096 if (Res->isNot(tok::comment) &&3097 DeletedTokens.find(Res) == DeletedTokens.end()) {3098 return Res;3099 }3100 }3101 return nullptr;3102 };3103 for (auto *Left = Start; Left;) {3104 auto *Right = NextNotDeleted(*Left);3105 if (!Right)3106 break;3107 if (Left->is(LK) && Right->is(RK)) {3108 deleteToken(DeleteLeft ? Left : Right);3109 for (auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next)3110 deleteToken(Tok);3111 // If the right token is deleted, we should keep the left token3112 // unchanged and pair it with the new right token.3113 if (!DeleteLeft)3114 continue;3115 }3116 Left = Right;3117 }3118 }3119 3120 template <typename LeftKind, typename RightKind>3121 void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) {3122 cleanupPair(Start, LK, RK, /*DeleteLeft=*/true);3123 }3124 3125 template <typename LeftKind, typename RightKind>3126 void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) {3127 cleanupPair(Start, LK, RK, /*DeleteLeft=*/false);3128 }3129 3130 // Delete the given token.3131 inline void deleteToken(FormatToken *Tok) {3132 if (Tok)3133 DeletedTokens.insert(Tok);3134 }3135 3136 tooling::Replacements generateFixes() {3137 tooling::Replacements Fixes;3138 SmallVector<FormatToken *> Tokens;3139 std::copy(DeletedTokens.begin(), DeletedTokens.end(),3140 std::back_inserter(Tokens));3141 3142 // Merge multiple continuous token deletions into one big deletion so that3143 // the number of replacements can be reduced. This makes computing affected3144 // ranges more efficient when we run reformat on the changed code.3145 unsigned Idx = 0;3146 while (Idx < Tokens.size()) {3147 unsigned St = Idx, End = Idx;3148 while ((End + 1) < Tokens.size() && Tokens[End]->Next == Tokens[End + 1])3149 ++End;3150 auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(),3151 Tokens[End]->Tok.getEndLoc());3152 auto Err =3153 Fixes.add(tooling::Replacement(Env.getSourceManager(), SR, ""));3154 // FIXME: better error handling. for now just print error message and skip3155 // for the release version.3156 if (Err) {3157 llvm::errs() << toString(std::move(Err)) << "\n";3158 assert(false && "Fixes must not conflict!");3159 }3160 Idx = End + 1;3161 }3162 3163 return Fixes;3164 }3165 3166 // Class for less-than inequality comparason for the set `RedundantTokens`.3167 // We store tokens in the order they appear in the translation unit so that3168 // we do not need to sort them in `generateFixes()`.3169 struct FormatTokenLess {3170 FormatTokenLess(const SourceManager &SM) : SM(SM) {}3171 3172 bool operator()(const FormatToken *LHS, const FormatToken *RHS) const {3173 return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(),3174 RHS->Tok.getLocation());3175 }3176 const SourceManager &SM;3177 };3178 3179 // Tokens to be deleted.3180 std::set<FormatToken *, FormatTokenLess> DeletedTokens;3181};3182 3183class ObjCHeaderStyleGuesser : public TokenAnalyzer {3184public:3185 ObjCHeaderStyleGuesser(const Environment &Env, const FormatStyle &Style)3186 : TokenAnalyzer(Env, Style), IsObjC(false) {}3187 3188 std::pair<tooling::Replacements, unsigned>3189 analyze(TokenAnnotator &Annotator,3190 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,3191 FormatTokenLexer &Tokens) override {3192 assert(Style.Language == FormatStyle::LK_Cpp);3193 IsObjC = guessIsObjC(Env.getSourceManager(), AnnotatedLines,3194 Tokens.getKeywords());3195 tooling::Replacements Result;3196 return {Result, 0};3197 }3198 3199 bool isObjC() { return IsObjC; }3200 3201private:3202 static bool3203 guessIsObjC(const SourceManager &SourceManager,3204 const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,3205 const AdditionalKeywords &Keywords) {3206 // Keep this array sorted, since we are binary searching over it.3207 static constexpr llvm::StringLiteral FoundationIdentifiers[] = {3208 "CGFloat",3209 "CGPoint",3210 "CGPointMake",3211 "CGPointZero",3212 "CGRect",3213 "CGRectEdge",3214 "CGRectInfinite",3215 "CGRectMake",3216 "CGRectNull",3217 "CGRectZero",3218 "CGSize",3219 "CGSizeMake",3220 "CGVector",3221 "CGVectorMake",3222 "FOUNDATION_EXPORT", // This is an alias for FOUNDATION_EXTERN.3223 "FOUNDATION_EXTERN",3224 "NSAffineTransform",3225 "NSArray",3226 "NSAttributedString",3227 "NSBlockOperation",3228 "NSBundle",3229 "NSCache",3230 "NSCalendar",3231 "NSCharacterSet",3232 "NSCountedSet",3233 "NSData",3234 "NSDataDetector",3235 "NSDecimal",3236 "NSDecimalNumber",3237 "NSDictionary",3238 "NSEdgeInsets",3239 "NSError",3240 "NSErrorDomain",3241 "NSHashTable",3242 "NSIndexPath",3243 "NSIndexSet",3244 "NSInteger",3245 "NSInvocationOperation",3246 "NSLocale",3247 "NSMapTable",3248 "NSMutableArray",3249 "NSMutableAttributedString",3250 "NSMutableCharacterSet",3251 "NSMutableData",3252 "NSMutableDictionary",3253 "NSMutableIndexSet",3254 "NSMutableOrderedSet",3255 "NSMutableSet",3256 "NSMutableString",3257 "NSNumber",3258 "NSNumberFormatter",3259 "NSObject",3260 "NSOperation",3261 "NSOperationQueue",3262 "NSOperationQueuePriority",3263 "NSOrderedSet",3264 "NSPoint",3265 "NSPointerArray",3266 "NSQualityOfService",3267 "NSRange",3268 "NSRect",3269 "NSRegularExpression",3270 "NSSet",3271 "NSSize",3272 "NSString",3273 "NSTimeZone",3274 "NSUInteger",3275 "NSURL",3276 "NSURLComponents",3277 "NSURLQueryItem",3278 "NSUUID",3279 "NSValue",3280 "NS_ASSUME_NONNULL_BEGIN",3281 "UIImage",3282 "UIView",3283 };3284 assert(llvm::is_sorted(FoundationIdentifiers));3285 3286 for (auto *Line : AnnotatedLines) {3287 if (Line->First && (Line->First->TokenText.starts_with("#") ||3288 Line->First->TokenText == "__pragma" ||3289 Line->First->TokenText == "_Pragma")) {3290 continue;3291 }3292 for (const FormatToken *FormatTok = Line->First; FormatTok;3293 FormatTok = FormatTok->Next) {3294 if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) &&3295 (FormatTok->isNot(tok::objc_not_keyword) ||3296 FormatTok->isOneOf(tok::numeric_constant, tok::l_square,3297 tok::l_brace))) ||3298 (FormatTok->Tok.isAnyIdentifier() &&3299 llvm::binary_search(FoundationIdentifiers,3300 FormatTok->TokenText)) ||3301 FormatTok->is(TT_ObjCStringLiteral) ||3302 FormatTok->isOneOf(Keywords.kw_NS_CLOSED_ENUM, Keywords.kw_NS_ENUM,3303 Keywords.kw_NS_ERROR_ENUM,3304 Keywords.kw_NS_OPTIONS, TT_ObjCBlockLBrace,3305 TT_ObjCBlockLParen, TT_ObjCDecl, TT_ObjCForIn,3306 TT_ObjCMethodExpr, TT_ObjCMethodSpecifier,3307 TT_ObjCProperty, TT_ObjCSelector)) {3308 LLVM_DEBUG(llvm::dbgs()3309 << "Detected ObjC at location "3310 << FormatTok->Tok.getLocation().printToString(3311 SourceManager)3312 << " token: " << FormatTok->TokenText << " token type: "3313 << getTokenTypeName(FormatTok->getType()) << "\n");3314 return true;3315 }3316 }3317 if (guessIsObjC(SourceManager, Line->Children, Keywords))3318 return true;3319 }3320 return false;3321 }3322 3323 bool IsObjC;3324};3325 3326struct IncludeDirective {3327 StringRef Filename;3328 StringRef Text;3329 unsigned Offset;3330 int Category;3331 int Priority;3332};3333 3334struct JavaImportDirective {3335 StringRef Identifier;3336 StringRef Text;3337 unsigned Offset;3338 SmallVector<StringRef> AssociatedCommentLines;3339 bool IsStatic;3340};3341 3342} // end anonymous namespace3343 3344// Determines whether 'Ranges' intersects with ('Start', 'End').3345static bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start,3346 unsigned End) {3347 for (const auto &Range : Ranges) {3348 if (Range.getOffset() < End &&3349 Range.getOffset() + Range.getLength() > Start) {3350 return true;3351 }3352 }3353 return false;3354}3355 3356// Returns a pair (Index, OffsetToEOL) describing the position of the cursor3357// before sorting/deduplicating. Index is the index of the include under the3358// cursor in the original set of includes. If this include has duplicates, it is3359// the index of the first of the duplicates as the others are going to be3360// removed. OffsetToEOL describes the cursor's position relative to the end of3361// its current line.3362// If `Cursor` is not on any #include, `Index` will be3363// std::numeric_limits<unsigned>::max().3364static std::pair<unsigned, unsigned>3365FindCursorIndex(const ArrayRef<IncludeDirective> &Includes,3366 const ArrayRef<unsigned> &Indices, unsigned Cursor) {3367 unsigned CursorIndex = std::numeric_limits<unsigned>::max();3368 unsigned OffsetToEOL = 0;3369 for (int i = 0, e = Includes.size(); i != e; ++i) {3370 unsigned Start = Includes[Indices[i]].Offset;3371 unsigned End = Start + Includes[Indices[i]].Text.size();3372 if (!(Cursor >= Start && Cursor < End))3373 continue;3374 CursorIndex = Indices[i];3375 OffsetToEOL = End - Cursor;3376 // Put the cursor on the only remaining #include among the duplicate3377 // #includes.3378 while (--i >= 0 && Includes[CursorIndex].Text == Includes[Indices[i]].Text)3379 CursorIndex = i;3380 break;3381 }3382 return std::make_pair(CursorIndex, OffsetToEOL);3383}3384 3385// Replace all "\r\n" with "\n".3386std::string replaceCRLF(const std::string &Code) {3387 std::string NewCode;3388 size_t Pos = 0, LastPos = 0;3389 3390 do {3391 Pos = Code.find("\r\n", LastPos);3392 if (Pos == LastPos) {3393 ++LastPos;3394 continue;3395 }3396 if (Pos == std::string::npos) {3397 NewCode += Code.substr(LastPos);3398 break;3399 }3400 NewCode += Code.substr(LastPos, Pos - LastPos) + "\n";3401 LastPos = Pos + 2;3402 } while (Pos != std::string::npos);3403 3404 return NewCode;3405}3406 3407// Sorts and deduplicate a block of includes given by 'Includes' alphabetically3408// adding the necessary replacement to 'Replaces'. 'Includes' must be in strict3409// source order.3410// #include directives with the same text will be deduplicated, and only the3411// first #include in the duplicate #includes remains. If the `Cursor` is3412// provided and put on a deleted #include, it will be moved to the remaining3413// #include in the duplicate #includes.3414static void sortCppIncludes(const FormatStyle &Style,3415 const ArrayRef<IncludeDirective> &Includes,3416 ArrayRef<tooling::Range> Ranges, StringRef FileName,3417 StringRef Code, tooling::Replacements &Replaces,3418 unsigned *Cursor) {3419 tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName);3420 const unsigned IncludesBeginOffset = Includes.front().Offset;3421 const unsigned IncludesEndOffset =3422 Includes.back().Offset + Includes.back().Text.size();3423 const unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset;3424 if (!affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset))3425 return;3426 SmallVector<unsigned, 16> Indices =3427 llvm::to_vector<16>(llvm::seq<unsigned>(0, Includes.size()));3428 3429 if (Style.SortIncludes.Enabled) {3430 stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {3431 SmallString<128> LHSStem, RHSStem;3432 if (Style.SortIncludes.IgnoreExtension) {3433 LHSStem = Includes[LHSI].Filename;3434 RHSStem = Includes[RHSI].Filename;3435 llvm::sys::path::replace_extension(LHSStem, "");3436 llvm::sys::path::replace_extension(RHSStem, "");3437 }3438 std::string LHSStemLower, RHSStemLower;3439 std::string LHSFilenameLower, RHSFilenameLower;3440 if (Style.SortIncludes.IgnoreCase) {3441 LHSStemLower = LHSStem.str().lower();3442 RHSStemLower = RHSStem.str().lower();3443 LHSFilenameLower = Includes[LHSI].Filename.lower();3444 RHSFilenameLower = Includes[RHSI].Filename.lower();3445 }3446 return std::tie(Includes[LHSI].Priority, LHSStemLower, LHSStem,3447 LHSFilenameLower, Includes[LHSI].Filename) <3448 std::tie(Includes[RHSI].Priority, RHSStemLower, RHSStem,3449 RHSFilenameLower, Includes[RHSI].Filename);3450 });3451 }3452 3453 // The index of the include on which the cursor will be put after3454 // sorting/deduplicating.3455 unsigned CursorIndex;3456 // The offset from cursor to the end of line.3457 unsigned CursorToEOLOffset;3458 if (Cursor) {3459 std::tie(CursorIndex, CursorToEOLOffset) =3460 FindCursorIndex(Includes, Indices, *Cursor);3461 }3462 3463 // Deduplicate #includes.3464 Indices.erase(llvm::unique(Indices,3465 [&](unsigned LHSI, unsigned RHSI) {3466 return Includes[LHSI].Text.trim() ==3467 Includes[RHSI].Text.trim();3468 }),3469 Indices.end());3470 3471 int CurrentCategory = Includes.front().Category;3472 3473 // If the #includes are out of order, we generate a single replacement fixing3474 // the entire block. Otherwise, no replacement is generated.3475 // In case Style.IncldueStyle.IncludeBlocks != IBS_Preserve, this check is not3476 // enough as additional newlines might be added or removed across #include3477 // blocks. This we handle below by generating the updated #include blocks and3478 // comparing it to the original.3479 if (Indices.size() == Includes.size() && is_sorted(Indices) &&3480 Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Preserve) {3481 return;3482 }3483 3484 const auto OldCursor = Cursor ? *Cursor : 0;3485 std::string result;3486 for (unsigned Index : Indices) {3487 if (!result.empty()) {3488 result += "\n";3489 if (Style.IncludeStyle.IncludeBlocks ==3490 tooling::IncludeStyle::IBS_Regroup &&3491 CurrentCategory != Includes[Index].Category) {3492 result += "\n";3493 }3494 }3495 result += Includes[Index].Text;3496 if (Cursor && CursorIndex == Index)3497 *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset;3498 CurrentCategory = Includes[Index].Category;3499 }3500 3501 if (Cursor && *Cursor >= IncludesEndOffset)3502 *Cursor += result.size() - IncludesBlockSize;3503 3504 // If the #includes are out of order, we generate a single replacement fixing3505 // the entire range of blocks. Otherwise, no replacement is generated.3506 if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr(3507 IncludesBeginOffset, IncludesBlockSize)))) {3508 if (Cursor)3509 *Cursor = OldCursor;3510 return;3511 }3512 3513 auto Err = Replaces.add(tooling::Replacement(3514 FileName, Includes.front().Offset, IncludesBlockSize, result));3515 // FIXME: better error handling. For now, just skip the replacement for the3516 // release version.3517 if (Err) {3518 llvm::errs() << toString(std::move(Err)) << "\n";3519 assert(false);3520 }3521}3522 3523tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,3524 ArrayRef<tooling::Range> Ranges,3525 StringRef FileName,3526 tooling::Replacements &Replaces,3527 unsigned *Cursor) {3528 unsigned Prev = llvm::StringSwitch<size_t>(Code)3529 .StartsWith("\xEF\xBB\xBF", 3) // UTF-8 BOM3530 .Default(0);3531 unsigned SearchFrom = 0;3532 SmallVector<StringRef, 4> Matches;3533 SmallVector<IncludeDirective, 16> IncludesInBlock;3534 3535 // In compiled files, consider the first #include to be the main #include of3536 // the file if it is not a system #include. This ensures that the header3537 // doesn't have hidden dependencies3538 // (http://llvm.org/docs/CodingStandards.html#include-style).3539 //3540 // FIXME: Do some validation, e.g. edit distance of the base name, to fix3541 // cases where the first #include is unlikely to be the main header.3542 tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName);3543 bool FirstIncludeBlock = true;3544 bool MainIncludeFound = false;3545 bool FormattingOff = false;3546 3547 // '[' must be the first and '-' the last character inside [...].3548 llvm::Regex RawStringRegex(3549 "R\"([][A-Za-z0-9_{}#<>%:;.?*+/^&\\$|~!=,'-]*)\\(");3550 SmallVector<StringRef, 2> RawStringMatches;3551 std::string RawStringTermination = ")\"";3552 3553 for (const auto Size = Code.size(); SearchFrom < Size;) {3554 size_t Pos = SearchFrom;3555 if (Code[SearchFrom] != '\n') {3556 do { // Search for the first newline while skipping line splices.3557 ++Pos;3558 Pos = Code.find('\n', Pos);3559 } while (Pos != StringRef::npos && Code[Pos - 1] == '\\');3560 }3561 3562 StringRef Line =3563 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);3564 3565 StringRef Trimmed = Line.trim();3566 3567 // #includes inside raw string literals need to be ignored.3568 // or we will sort the contents of the string.3569 // Skip past until we think we are at the rawstring literal close.3570 if (RawStringRegex.match(Trimmed, &RawStringMatches)) {3571 std::string CharSequence = RawStringMatches[1].str();3572 RawStringTermination = ")" + CharSequence + "\"";3573 FormattingOff = true;3574 }3575 3576 if (Trimmed.contains(RawStringTermination))3577 FormattingOff = false;3578 3579 bool IsBlockComment = false;3580 3581 if (isClangFormatOff(Trimmed)) {3582 FormattingOff = true;3583 } else if (isClangFormatOn(Trimmed)) {3584 FormattingOff = false;3585 } else if (Trimmed.starts_with("/*")) {3586 IsBlockComment = true;3587 Pos = Code.find("*/", SearchFrom + 2);3588 }3589 3590 const bool EmptyLineSkipped =3591 Trimmed.empty() &&3592 (Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Merge ||3593 Style.IncludeStyle.IncludeBlocks ==3594 tooling::IncludeStyle::IBS_Regroup);3595 3596 bool MergeWithNextLine = Trimmed.ends_with("\\");3597 if (!FormattingOff && !MergeWithNextLine) {3598 if (!IsBlockComment &&3599 tooling::HeaderIncludes::IncludeRegex.match(Trimmed, &Matches)) {3600 StringRef IncludeName = Matches[2];3601 if (Trimmed.contains("/*") && !Trimmed.contains("*/")) {3602 // #include with a start of a block comment, but without the end.3603 // Need to keep all the lines until the end of the comment together.3604 // FIXME: This is somehow simplified check that probably does not work3605 // correctly if there are multiple comments on a line.3606 Pos = Code.find("*/", SearchFrom);3607 Line = Code.substr(3608 Prev, (Pos != StringRef::npos ? Pos + 2 : Code.size()) - Prev);3609 }3610 int Category = Categories.getIncludePriority(3611 IncludeName,3612 /*CheckMainHeader=*/!MainIncludeFound && FirstIncludeBlock);3613 int Priority = Categories.getSortIncludePriority(3614 IncludeName, !MainIncludeFound && FirstIncludeBlock);3615 if (Category == 0)3616 MainIncludeFound = true;3617 IncludesInBlock.push_back(3618 {IncludeName, Line, Prev, Category, Priority});3619 } else if (!IncludesInBlock.empty() && !EmptyLineSkipped) {3620 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code,3621 Replaces, Cursor);3622 IncludesInBlock.clear();3623 if (Trimmed.starts_with("#pragma hdrstop")) // Precompiled headers.3624 FirstIncludeBlock = true;3625 else3626 FirstIncludeBlock = false;3627 }3628 }3629 if (Pos == StringRef::npos || Pos + 1 == Code.size())3630 break;3631 3632 if (!MergeWithNextLine)3633 Prev = Pos + 1;3634 SearchFrom = Pos + 1;3635 }3636 if (!IncludesInBlock.empty()) {3637 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, Replaces,3638 Cursor);3639 }3640 return Replaces;3641}3642 3643// Returns group number to use as a first order sort on imports. Gives3644// std::numeric_limits<unsigned>::max() if the import does not match any given3645// groups.3646static unsigned findJavaImportGroup(const FormatStyle &Style,3647 StringRef ImportIdentifier) {3648 unsigned LongestMatchIndex = std::numeric_limits<unsigned>::max();3649 unsigned LongestMatchLength = 0;3650 for (unsigned I = 0; I < Style.JavaImportGroups.size(); I++) {3651 const std::string &GroupPrefix = Style.JavaImportGroups[I];3652 if (ImportIdentifier.starts_with(GroupPrefix) &&3653 GroupPrefix.length() > LongestMatchLength) {3654 LongestMatchIndex = I;3655 LongestMatchLength = GroupPrefix.length();3656 }3657 }3658 return LongestMatchIndex;3659}3660 3661// Sorts and deduplicates a block of includes given by 'Imports' based on3662// JavaImportGroups, then adding the necessary replacement to 'Replaces'.3663// Import declarations with the same text will be deduplicated. Between each3664// import group, a newline is inserted, and within each import group, a3665// lexicographic sort based on ASCII value is performed.3666static void sortJavaImports(const FormatStyle &Style,3667 const ArrayRef<JavaImportDirective> &Imports,3668 ArrayRef<tooling::Range> Ranges, StringRef FileName,3669 StringRef Code, tooling::Replacements &Replaces) {3670 unsigned ImportsBeginOffset = Imports.front().Offset;3671 unsigned ImportsEndOffset =3672 Imports.back().Offset + Imports.back().Text.size();3673 unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset;3674 if (!affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset))3675 return;3676 3677 SmallVector<unsigned, 16> Indices =3678 llvm::to_vector<16>(llvm::seq<unsigned>(0, Imports.size()));3679 SmallVector<unsigned, 16> JavaImportGroups;3680 JavaImportGroups.reserve(Imports.size());3681 for (const JavaImportDirective &Import : Imports)3682 JavaImportGroups.push_back(findJavaImportGroup(Style, Import.Identifier));3683 3684 bool StaticImportAfterNormalImport =3685 Style.SortJavaStaticImport == FormatStyle::SJSIO_After;3686 sort(Indices, [&](unsigned LHSI, unsigned RHSI) {3687 // Negating IsStatic to push static imports above non-static imports.3688 return std::make_tuple(!Imports[LHSI].IsStatic ^3689 StaticImportAfterNormalImport,3690 JavaImportGroups[LHSI], Imports[LHSI].Identifier) <3691 std::make_tuple(!Imports[RHSI].IsStatic ^3692 StaticImportAfterNormalImport,3693 JavaImportGroups[RHSI], Imports[RHSI].Identifier);3694 });3695 3696 // Deduplicate imports.3697 Indices.erase(llvm::unique(Indices,3698 [&](unsigned LHSI, unsigned RHSI) {3699 return Imports[LHSI].Text == Imports[RHSI].Text;3700 }),3701 Indices.end());3702 3703 bool CurrentIsStatic = Imports[Indices.front()].IsStatic;3704 unsigned CurrentImportGroup = JavaImportGroups[Indices.front()];3705 3706 std::string result;3707 for (unsigned Index : Indices) {3708 if (!result.empty()) {3709 result += "\n";3710 if (CurrentIsStatic != Imports[Index].IsStatic ||3711 CurrentImportGroup != JavaImportGroups[Index]) {3712 result += "\n";3713 }3714 }3715 for (StringRef CommentLine : Imports[Index].AssociatedCommentLines) {3716 result += CommentLine;3717 result += "\n";3718 }3719 result += Imports[Index].Text;3720 CurrentIsStatic = Imports[Index].IsStatic;3721 CurrentImportGroup = JavaImportGroups[Index];3722 }3723 3724 // If the imports are out of order, we generate a single replacement fixing3725 // the entire block. Otherwise, no replacement is generated.3726 if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr(3727 Imports.front().Offset, ImportsBlockSize)))) {3728 return;3729 }3730 3731 auto Err = Replaces.add(tooling::Replacement(FileName, Imports.front().Offset,3732 ImportsBlockSize, result));3733 // FIXME: better error handling. For now, just skip the replacement for the3734 // release version.3735 if (Err) {3736 llvm::errs() << toString(std::move(Err)) << "\n";3737 assert(false);3738 }3739}3740 3741namespace {3742 3743const char JavaImportRegexPattern[] =3744 "^[\t ]*import[\t ]+(static[\t ]*)?([^\t ]*)[\t ]*;";3745 3746} // anonymous namespace3747 3748tooling::Replacements sortJavaImports(const FormatStyle &Style, StringRef Code,3749 ArrayRef<tooling::Range> Ranges,3750 StringRef FileName,3751 tooling::Replacements &Replaces) {3752 unsigned Prev = 0;3753 unsigned SearchFrom = 0;3754 llvm::Regex ImportRegex(JavaImportRegexPattern);3755 SmallVector<StringRef, 4> Matches;3756 SmallVector<JavaImportDirective, 16> ImportsInBlock;3757 SmallVector<StringRef> AssociatedCommentLines;3758 3759 bool FormattingOff = false;3760 3761 for (;;) {3762 auto Pos = Code.find('\n', SearchFrom);3763 StringRef Line =3764 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);3765 3766 StringRef Trimmed = Line.trim();3767 if (isClangFormatOff(Trimmed))3768 FormattingOff = true;3769 else if (isClangFormatOn(Trimmed))3770 FormattingOff = false;3771 3772 if (ImportRegex.match(Line, &Matches)) {3773 if (FormattingOff) {3774 // If at least one import line has formatting turned off, turn off3775 // formatting entirely.3776 return Replaces;3777 }3778 StringRef Static = Matches[1];3779 StringRef Identifier = Matches[2];3780 bool IsStatic = false;3781 if (Static.contains("static"))3782 IsStatic = true;3783 ImportsInBlock.push_back(3784 {Identifier, Line, Prev, AssociatedCommentLines, IsStatic});3785 AssociatedCommentLines.clear();3786 } else if (!Trimmed.empty() && !ImportsInBlock.empty()) {3787 // Associating comments within the imports with the nearest import below3788 AssociatedCommentLines.push_back(Line);3789 }3790 Prev = Pos + 1;3791 if (Pos == StringRef::npos || Pos + 1 == Code.size())3792 break;3793 SearchFrom = Pos + 1;3794 }3795 if (!ImportsInBlock.empty())3796 sortJavaImports(Style, ImportsInBlock, Ranges, FileName, Code, Replaces);3797 return Replaces;3798}3799 3800bool isMpegTS(StringRef Code) {3801 // MPEG transport streams use the ".ts" file extension. clang-format should3802 // not attempt to format those. MPEG TS' frame format starts with 0x47 every3803 // 189 bytes - detect that and return.3804 return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47;3805}3806 3807bool isLikelyXml(StringRef Code) { return Code.ltrim().starts_with("<"); }3808 3809tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code,3810 ArrayRef<tooling::Range> Ranges,3811 StringRef FileName, unsigned *Cursor) {3812 tooling::Replacements Replaces;3813 if (!Style.SortIncludes.Enabled || Style.DisableFormat)3814 return Replaces;3815 if (isLikelyXml(Code))3816 return Replaces;3817 if (Style.isJavaScript()) {3818 if (isMpegTS(Code))3819 return Replaces;3820 return sortJavaScriptImports(Style, Code, Ranges, FileName);3821 }3822 if (Style.isJava())3823 return sortJavaImports(Style, Code, Ranges, FileName, Replaces);3824 if (Style.isCpp())3825 sortCppIncludes(Style, Code, Ranges, FileName, Replaces, Cursor);3826 return Replaces;3827}3828 3829template <typename T>3830static Expected<tooling::Replacements>3831processReplacements(T ProcessFunc, StringRef Code,3832 const tooling::Replacements &Replaces,3833 const FormatStyle &Style) {3834 if (Replaces.empty())3835 return tooling::Replacements();3836 3837 auto NewCode = applyAllReplacements(Code, Replaces);3838 if (!NewCode)3839 return NewCode.takeError();3840 std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges();3841 StringRef FileName = Replaces.begin()->getFilePath();3842 3843 tooling::Replacements FormatReplaces =3844 ProcessFunc(Style, *NewCode, ChangedRanges, FileName);3845 3846 return Replaces.merge(FormatReplaces);3847}3848 3849Expected<tooling::Replacements>3850formatReplacements(StringRef Code, const tooling::Replacements &Replaces,3851 const FormatStyle &Style) {3852 // We need to use lambda function here since there are two versions of3853 // `sortIncludes`.3854 auto SortIncludes = [](const FormatStyle &Style, StringRef Code,3855 std::vector<tooling::Range> Ranges,3856 StringRef FileName) -> tooling::Replacements {3857 return sortIncludes(Style, Code, Ranges, FileName);3858 };3859 auto SortedReplaces =3860 processReplacements(SortIncludes, Code, Replaces, Style);3861 if (!SortedReplaces)3862 return SortedReplaces.takeError();3863 3864 // We need to use lambda function here since there are two versions of3865 // `reformat`.3866 auto Reformat = [](const FormatStyle &Style, StringRef Code,3867 std::vector<tooling::Range> Ranges,3868 StringRef FileName) -> tooling::Replacements {3869 return reformat(Style, Code, Ranges, FileName);3870 };3871 return processReplacements(Reformat, Code, *SortedReplaces, Style);3872}3873 3874namespace {3875 3876inline bool isHeaderInsertion(const tooling::Replacement &Replace) {3877 return Replace.getOffset() == std::numeric_limits<unsigned>::max() &&3878 Replace.getLength() == 0 &&3879 tooling::HeaderIncludes::IncludeRegex.match(3880 Replace.getReplacementText());3881}3882 3883inline bool isHeaderDeletion(const tooling::Replacement &Replace) {3884 return Replace.getOffset() == std::numeric_limits<unsigned>::max() &&3885 Replace.getLength() == 1;3886}3887 3888// FIXME: insert empty lines between newly created blocks.3889tooling::Replacements3890fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,3891 const FormatStyle &Style) {3892 if (!Style.isCpp())3893 return Replaces;3894 3895 tooling::Replacements HeaderInsertions;3896 std::set<StringRef> HeadersToDelete;3897 tooling::Replacements Result;3898 for (const auto &R : Replaces) {3899 if (isHeaderInsertion(R)) {3900 // Replacements from \p Replaces must be conflict-free already, so we can3901 // simply consume the error.3902 consumeError(HeaderInsertions.add(R));3903 } else if (isHeaderDeletion(R)) {3904 HeadersToDelete.insert(R.getReplacementText());3905 } else if (R.getOffset() == std::numeric_limits<unsigned>::max()) {3906 llvm::errs() << "Insertions other than header #include insertion are "3907 "not supported! "3908 << R.getReplacementText() << "\n";3909 } else {3910 consumeError(Result.add(R));3911 }3912 }3913 if (HeaderInsertions.empty() && HeadersToDelete.empty())3914 return Replaces;3915 3916 StringRef FileName = Replaces.begin()->getFilePath();3917 tooling::HeaderIncludes Includes(FileName, Code, Style.IncludeStyle);3918 3919 for (const auto &Header : HeadersToDelete) {3920 tooling::Replacements Replaces =3921 Includes.remove(Header.trim("\"<>"), Header.starts_with("<"));3922 for (const auto &R : Replaces) {3923 auto Err = Result.add(R);3924 if (Err) {3925 // Ignore the deletion on conflict.3926 llvm::errs() << "Failed to add header deletion replacement for "3927 << Header << ": " << toString(std::move(Err)) << "\n";3928 }3929 }3930 }3931 3932 SmallVector<StringRef, 4> Matches;3933 for (const auto &R : HeaderInsertions) {3934 auto IncludeDirective = R.getReplacementText();3935 bool Matched =3936 tooling::HeaderIncludes::IncludeRegex.match(IncludeDirective, &Matches);3937 assert(Matched && "Header insertion replacement must have replacement text "3938 "'#include ...'");3939 (void)Matched;3940 auto IncludeName = Matches[2];3941 auto Replace =3942 Includes.insert(IncludeName.trim("\"<>"), IncludeName.starts_with("<"),3943 tooling::IncludeDirective::Include);3944 if (Replace) {3945 auto Err = Result.add(*Replace);3946 if (Err) {3947 consumeError(std::move(Err));3948 unsigned NewOffset =3949 Result.getShiftedCodePosition(Replace->getOffset());3950 auto Shifted = tooling::Replacement(FileName, NewOffset, 0,3951 Replace->getReplacementText());3952 Result = Result.merge(tooling::Replacements(Shifted));3953 }3954 }3955 }3956 return Result;3957}3958 3959} // anonymous namespace3960 3961Expected<tooling::Replacements>3962cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces,3963 const FormatStyle &Style) {3964 // We need to use lambda function here since there are two versions of3965 // `cleanup`.3966 auto Cleanup = [](const FormatStyle &Style, StringRef Code,3967 ArrayRef<tooling::Range> Ranges,3968 StringRef FileName) -> tooling::Replacements {3969 return cleanup(Style, Code, Ranges, FileName);3970 };3971 // Make header insertion replacements insert new headers into correct blocks.3972 tooling::Replacements NewReplaces =3973 fixCppIncludeInsertions(Code, Replaces, Style);3974 return cantFail(processReplacements(Cleanup, Code, NewReplaces, Style));3975}3976 3977namespace internal {3978std::pair<tooling::Replacements, unsigned>3979reformat(const FormatStyle &Style, StringRef Code,3980 ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn,3981 unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName,3982 FormattingAttemptStatus *Status) {3983 FormatStyle Expanded = Style;3984 expandPresetsBraceWrapping(Expanded);3985 expandPresetsSpaceBeforeParens(Expanded);3986 expandPresetsSpacesInParens(Expanded);3987 Expanded.InsertBraces = false;3988 Expanded.RemoveBracesLLVM = false;3989 Expanded.RemoveParentheses = FormatStyle::RPS_Leave;3990 Expanded.RemoveSemicolon = false;3991 switch (Expanded.RequiresClausePosition) {3992 case FormatStyle::RCPS_SingleLine:3993 case FormatStyle::RCPS_WithPreceding:3994 Expanded.IndentRequiresClause = false;3995 break;3996 default:3997 break;3998 }3999 4000 if (Expanded.DisableFormat)4001 return {tooling::Replacements(), 0};4002 if (isLikelyXml(Code))4003 return {tooling::Replacements(), 0};4004 if (Expanded.isJavaScript() && isMpegTS(Code))4005 return {tooling::Replacements(), 0};4006 4007 // JSON only needs the formatting passing.4008 if (Style.isJson()) {4009 std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));4010 auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn,4011 NextStartColumn, LastStartColumn);4012 if (!Env)4013 return {};4014 // Perform the actual formatting pass.4015 tooling::Replacements Replaces =4016 Formatter(*Env, Style, Status).process().first;4017 // add a replacement to remove the "x = " from the result.4018 if (Code.starts_with("x = ")) {4019 Replaces = Replaces.merge(4020 tooling::Replacements(tooling::Replacement(FileName, 0, 4, "")));4021 }4022 // apply the reformatting changes and the removal of "x = ".4023 if (applyAllReplacements(Code, Replaces))4024 return {Replaces, 0};4025 return {tooling::Replacements(), 0};4026 }4027 4028 auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn,4029 NextStartColumn, LastStartColumn);4030 if (!Env)4031 return {};4032 4033 typedef std::function<std::pair<tooling::Replacements, unsigned>(4034 const Environment &)>4035 AnalyzerPass;4036 4037 SmallVector<AnalyzerPass, 16> Passes;4038 4039 Passes.emplace_back([&](const Environment &Env) {4040 return IntegerLiteralSeparatorFixer().process(Env, Expanded);4041 });4042 4043 Passes.emplace_back([&](const Environment &Env) {4044 return NumericLiteralCaseFixer().process(Env, Expanded);4045 });4046 4047 if (Style.isCpp()) {4048 if (Style.QualifierAlignment != FormatStyle::QAS_Leave)4049 addQualifierAlignmentFixerPasses(Expanded, Passes);4050 4051 if (Style.RemoveParentheses != FormatStyle::RPS_Leave) {4052 FormatStyle S = Expanded;4053 S.RemoveParentheses = Style.RemoveParentheses;4054 Passes.emplace_back([&, S = std::move(S)](const Environment &Env) {4055 return ParensRemover(Env, S).process(/*SkipAnnotation=*/true);4056 });4057 }4058 4059 if (Style.InsertBraces) {4060 FormatStyle S = Expanded;4061 S.InsertBraces = true;4062 Passes.emplace_back([&, S = std::move(S)](const Environment &Env) {4063 return BracesInserter(Env, S).process(/*SkipAnnotation=*/true);4064 });4065 }4066 4067 if (Style.RemoveBracesLLVM) {4068 FormatStyle S = Expanded;4069 S.RemoveBracesLLVM = true;4070 Passes.emplace_back([&, S = std::move(S)](const Environment &Env) {4071 return BracesRemover(Env, S).process(/*SkipAnnotation=*/true);4072 });4073 }4074 4075 if (Style.RemoveSemicolon) {4076 FormatStyle S = Expanded;4077 S.RemoveSemicolon = true;4078 Passes.emplace_back([&, S = std::move(S)](const Environment &Env) {4079 return SemiRemover(Env, S).process();4080 });4081 }4082 4083 if (Style.EnumTrailingComma != FormatStyle::ETC_Leave) {4084 Passes.emplace_back([&](const Environment &Env) {4085 return EnumTrailingCommaEditor(Env, Expanded)4086 .process(/*SkipAnnotation=*/true);4087 });4088 }4089 4090 if (Style.FixNamespaceComments) {4091 Passes.emplace_back([&](const Environment &Env) {4092 return NamespaceEndCommentsFixer(Env, Expanded).process();4093 });4094 }4095 4096 if (Style.SortUsingDeclarations != FormatStyle::SUD_Never) {4097 Passes.emplace_back([&](const Environment &Env) {4098 return UsingDeclarationsSorter(Env, Expanded).process();4099 });4100 }4101 }4102 4103 if (Style.SeparateDefinitionBlocks != FormatStyle::SDS_Leave) {4104 Passes.emplace_back([&](const Environment &Env) {4105 return DefinitionBlockSeparator(Env, Expanded).process();4106 });4107 }4108 4109 if (Style.Language == FormatStyle::LK_ObjC &&4110 !Style.ObjCPropertyAttributeOrder.empty()) {4111 Passes.emplace_back([&](const Environment &Env) {4112 return ObjCPropertyAttributeOrderFixer(Env, Expanded).process();4113 });4114 }4115 4116 if (Style.isJavaScript() &&4117 Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) {4118 Passes.emplace_back([&](const Environment &Env) {4119 return JavaScriptRequoter(Env, Expanded).process(/*SkipAnnotation=*/true);4120 });4121 }4122 4123 Passes.emplace_back([&](const Environment &Env) {4124 return Formatter(Env, Expanded, Status).process();4125 });4126 4127 if (Style.isJavaScript() &&4128 Style.InsertTrailingCommas == FormatStyle::TCS_Wrapped) {4129 Passes.emplace_back([&](const Environment &Env) {4130 return TrailingCommaInserter(Env, Expanded).process();4131 });4132 }4133 4134 std::optional<std::string> CurrentCode;4135 tooling::Replacements Fixes;4136 unsigned Penalty = 0;4137 for (size_t I = 0, E = Passes.size(); I < E; ++I) {4138 std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env);4139 auto NewCode = applyAllReplacements(4140 CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first);4141 if (NewCode) {4142 Fixes = Fixes.merge(PassFixes.first);4143 Penalty += PassFixes.second;4144 if (I + 1 < E) {4145 CurrentCode = std::move(*NewCode);4146 Env = Environment::make(4147 *CurrentCode, FileName,4148 tooling::calculateRangesAfterReplacements(Fixes, Ranges),4149 FirstStartColumn, NextStartColumn, LastStartColumn);4150 if (!Env)4151 return {};4152 }4153 }4154 }4155 4156 if (Style.QualifierAlignment != FormatStyle::QAS_Leave) {4157 // Don't make replacements that replace nothing. QualifierAlignment can4158 // produce them if one of its early passes changes e.g. `const volatile` to4159 // `volatile const` and then a later pass changes it back again.4160 tooling::Replacements NonNoOpFixes;4161 for (const tooling::Replacement &Fix : Fixes) {4162 StringRef OriginalCode = Code.substr(Fix.getOffset(), Fix.getLength());4163 if (OriginalCode != Fix.getReplacementText()) {4164 auto Err = NonNoOpFixes.add(Fix);4165 if (Err) {4166 llvm::errs() << "Error adding replacements : "4167 << toString(std::move(Err)) << "\n";4168 }4169 }4170 }4171 Fixes = std::move(NonNoOpFixes);4172 }4173 4174 return {Fixes, Penalty};4175}4176} // namespace internal4177 4178tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,4179 ArrayRef<tooling::Range> Ranges,4180 StringRef FileName,4181 FormattingAttemptStatus *Status) {4182 return internal::reformat(Style, Code, Ranges,4183 /*FirstStartColumn=*/0,4184 /*NextStartColumn=*/0,4185 /*LastStartColumn=*/0, FileName, Status)4186 .first;4187}4188 4189tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code,4190 ArrayRef<tooling::Range> Ranges,4191 StringRef FileName) {4192 // cleanups only apply to C++ (they mostly concern ctor commas etc.)4193 if (Style.Language != FormatStyle::LK_Cpp)4194 return tooling::Replacements();4195 auto Env = Environment::make(Code, FileName, Ranges);4196 if (!Env)4197 return {};4198 return Cleaner(*Env, Style).process().first;4199}4200 4201tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,4202 ArrayRef<tooling::Range> Ranges,4203 StringRef FileName, bool *IncompleteFormat) {4204 FormattingAttemptStatus Status;4205 auto Result = reformat(Style, Code, Ranges, FileName, &Status);4206 if (!Status.FormatComplete)4207 *IncompleteFormat = true;4208 return Result;4209}4210 4211tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style,4212 StringRef Code,4213 ArrayRef<tooling::Range> Ranges,4214 StringRef FileName) {4215 auto Env = Environment::make(Code, FileName, Ranges);4216 if (!Env)4217 return {};4218 return NamespaceEndCommentsFixer(*Env, Style).process().first;4219}4220 4221tooling::Replacements sortUsingDeclarations(const FormatStyle &Style,4222 StringRef Code,4223 ArrayRef<tooling::Range> Ranges,4224 StringRef FileName) {4225 auto Env = Environment::make(Code, FileName, Ranges);4226 if (!Env)4227 return {};4228 return UsingDeclarationsSorter(*Env, Style).process().first;4229}4230 4231LangOptions getFormattingLangOpts(const FormatStyle &Style) {4232 LangOptions LangOpts;4233 4234 auto LexingStd = Style.Standard;4235 if (LexingStd == FormatStyle::LS_Auto || LexingStd == FormatStyle::LS_Latest)4236 LexingStd = FormatStyle::LS_Cpp20;4237 4238 const bool SinceCpp11 = LexingStd >= FormatStyle::LS_Cpp11;4239 const bool SinceCpp20 = LexingStd >= FormatStyle::LS_Cpp20;4240 4241 switch (Style.Language) {4242 case FormatStyle::LK_C:4243 LangOpts.C11 = 1;4244 LangOpts.C23 = 1;4245 break;4246 case FormatStyle::LK_Cpp:4247 case FormatStyle::LK_ObjC:4248 LangOpts.CXXOperatorNames = 1;4249 LangOpts.CPlusPlus11 = SinceCpp11;4250 LangOpts.CPlusPlus14 = LexingStd >= FormatStyle::LS_Cpp14;4251 LangOpts.CPlusPlus17 = LexingStd >= FormatStyle::LS_Cpp17;4252 LangOpts.CPlusPlus20 = SinceCpp20;4253 [[fallthrough]];4254 default:4255 LangOpts.CPlusPlus = 1;4256 }4257 4258 LangOpts.Char8 = SinceCpp20;4259 // Turning on digraphs in standards before C++0x is error-prone, because e.g.4260 // the sequence "<::" will be unconditionally treated as "[:".4261 // Cf. Lexer::LexTokenInternal.4262 LangOpts.Digraphs = SinceCpp11;4263 4264 LangOpts.LineComment = 1;4265 LangOpts.Bool = 1;4266 LangOpts.ObjC = 1;4267 LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally.4268 LangOpts.DeclSpecKeyword = 1; // To get __declspec.4269 LangOpts.C99 = 1; // To get kw_restrict for non-underscore-prefixed restrict.4270 4271 return LangOpts;4272}4273 4274const char *StyleOptionHelpDescription =4275 "Set coding style. <string> can be:\n"4276 "1. A preset: LLVM, GNU, Google, Chromium, Microsoft,\n"4277 " Mozilla, WebKit.\n"4278 "2. 'file' to load style configuration from a\n"4279 " .clang-format file in one of the parent directories\n"4280 " of the source file (for stdin, see --assume-filename).\n"4281 " If no .clang-format file is found, falls back to\n"4282 " --fallback-style.\n"4283 " --style=file is the default.\n"4284 "3. 'file:<format_file_path>' to explicitly specify\n"4285 " the configuration file.\n"4286 "4. \"{key: value, ...}\" to set specific parameters, e.g.:\n"4287 " --style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";4288 4289static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) {4290 if (FileName.ends_with(".c"))4291 return FormatStyle::LK_C;4292 if (FileName.ends_with(".java"))4293 return FormatStyle::LK_Java;4294 if (FileName.ends_with_insensitive(".js") ||4295 FileName.ends_with_insensitive(".mjs") ||4296 FileName.ends_with_insensitive(".cjs") ||4297 FileName.ends_with_insensitive(".ts")) {4298 return FormatStyle::LK_JavaScript; // (module) JavaScript or TypeScript.4299 }4300 if (FileName.ends_with(".m") || FileName.ends_with(".mm"))4301 return FormatStyle::LK_ObjC;4302 if (FileName.ends_with_insensitive(".proto") ||4303 FileName.ends_with_insensitive(".protodevel")) {4304 return FormatStyle::LK_Proto;4305 }4306 // txtpb is the canonical extension, and textproto is the legacy canonical4307 // extension4308 // https://protobuf.dev/reference/protobuf/textformat-spec/#text-format-files4309 if (FileName.ends_with_insensitive(".txtpb") ||4310 FileName.ends_with_insensitive(".textpb") ||4311 FileName.ends_with_insensitive(".pb.txt") ||4312 FileName.ends_with_insensitive(".textproto") ||4313 FileName.ends_with_insensitive(".asciipb")) {4314 return FormatStyle::LK_TextProto;4315 }4316 if (FileName.ends_with_insensitive(".td"))4317 return FormatStyle::LK_TableGen;4318 if (FileName.ends_with_insensitive(".cs"))4319 return FormatStyle::LK_CSharp;4320 if (FileName.ends_with_insensitive(".json") ||4321 FileName.ends_with_insensitive(".ipynb")) {4322 return FormatStyle::LK_Json;4323 }4324 if (FileName.ends_with_insensitive(".sv") ||4325 FileName.ends_with_insensitive(".svh") ||4326 FileName.ends_with_insensitive(".v") ||4327 FileName.ends_with_insensitive(".vh")) {4328 return FormatStyle::LK_Verilog;4329 }4330 return FormatStyle::LK_Cpp;4331}4332 4333static FormatStyle::LanguageKind getLanguageByComment(const Environment &Env) {4334 const auto ID = Env.getFileID();4335 const auto &SourceMgr = Env.getSourceManager();4336 4337 LangOptions LangOpts;4338 LangOpts.CPlusPlus = 1;4339 LangOpts.LineComment = 1;4340 4341 Lexer Lex(ID, SourceMgr.getBufferOrFake(ID), SourceMgr, LangOpts);4342 Lex.SetCommentRetentionState(true);4343 4344 for (Token Tok; !Lex.LexFromRawLexer(Tok) && Tok.is(tok::comment);) {4345 auto Text = StringRef(SourceMgr.getCharacterData(Tok.getLocation()),4346 Tok.getLength());4347 if (!Text.consume_front("// clang-format Language:"))4348 continue;4349 4350 Text = Text.trim();4351 if (Text == "C")4352 return FormatStyle::LK_C;4353 if (Text == "Cpp")4354 return FormatStyle::LK_Cpp;4355 if (Text == "ObjC")4356 return FormatStyle::LK_ObjC;4357 }4358 4359 return FormatStyle::LK_None;4360}4361 4362FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) {4363 const auto GuessedLanguage = getLanguageByFileName(FileName);4364 if (GuessedLanguage == FormatStyle::LK_Cpp) {4365 auto Extension = llvm::sys::path::extension(FileName);4366 // If there's no file extension (or it's .h), we need to check the contents4367 // of the code to see if it contains Objective-C.4368 if (!Code.empty() && (Extension.empty() || Extension == ".h")) {4369 auto NonEmptyFileName = FileName.empty() ? "guess.h" : FileName;4370 Environment Env(Code, NonEmptyFileName, /*Ranges=*/{});4371 if (const auto Language = getLanguageByComment(Env);4372 Language != FormatStyle::LK_None) {4373 return Language;4374 }4375 ObjCHeaderStyleGuesser Guesser(Env, getLLVMStyle());4376 Guesser.process();4377 if (Guesser.isObjC())4378 return FormatStyle::LK_ObjC;4379 }4380 }4381 return GuessedLanguage;4382}4383 4384// Update StyleOptionHelpDescription above when changing this.4385const char *DefaultFormatStyle = "file";4386 4387const char *DefaultFallbackStyle = "LLVM";4388 4389llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>4390loadAndParseConfigFile(StringRef ConfigFile, llvm::vfs::FileSystem *FS,4391 FormatStyle *Style, bool AllowUnknownOptions,4392 llvm::SourceMgr::DiagHandlerTy DiagHandler,4393 bool IsDotHFile) {4394 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =4395 FS->getBufferForFile(ConfigFile.str());4396 if (auto EC = Text.getError())4397 return EC;4398 if (auto EC = parseConfiguration(*Text.get(), Style, AllowUnknownOptions,4399 DiagHandler, /*DiagHandlerCtx=*/nullptr,4400 IsDotHFile)) {4401 return EC;4402 }4403 return Text;4404}4405 4406Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,4407 StringRef FallbackStyleName, StringRef Code,4408 llvm::vfs::FileSystem *FS,4409 bool AllowUnknownOptions,4410 llvm::SourceMgr::DiagHandlerTy DiagHandler) {4411 FormatStyle Style = getLLVMStyle(guessLanguage(FileName, Code));4412 FormatStyle FallbackStyle = getNoStyle();4413 if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle))4414 return make_string_error("Invalid fallback style: " + FallbackStyleName);4415 4416 SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 1> ChildFormatTextToApply;4417 4418 if (StyleName.starts_with("{")) {4419 // Parse YAML/JSON style from the command line.4420 StringRef Source = "<command-line>";4421 if (std::error_code ec =4422 parseConfiguration(llvm::MemoryBufferRef(StyleName, Source), &Style,4423 AllowUnknownOptions, DiagHandler)) {4424 return make_string_error("Error parsing -style: " + ec.message());4425 }4426 4427 if (!Style.InheritsParentConfig)4428 return Style;4429 4430 ChildFormatTextToApply.emplace_back(4431 llvm::MemoryBuffer::getMemBuffer(StyleName, Source, false));4432 }4433 4434 if (!FS)4435 FS = llvm::vfs::getRealFileSystem().get();4436 assert(FS);4437 4438 const bool IsDotHFile = FileName.ends_with(".h");4439 4440 // User provided clang-format file using -style=file:path/to/format/file.4441 if (!Style.InheritsParentConfig &&4442 StyleName.starts_with_insensitive("file:")) {4443 auto ConfigFile = StyleName.substr(5);4444 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =4445 loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions,4446 DiagHandler, IsDotHFile);4447 if (auto EC = Text.getError()) {4448 return make_string_error("Error reading " + ConfigFile + ": " +4449 EC.message());4450 }4451 4452 LLVM_DEBUG(llvm::dbgs()4453 << "Using configuration file " << ConfigFile << "\n");4454 4455 if (!Style.InheritsParentConfig)4456 return Style;4457 4458 // Search for parent configs starting from the parent directory of4459 // ConfigFile.4460 FileName = ConfigFile;4461 ChildFormatTextToApply.emplace_back(std::move(*Text));4462 }4463 4464 // If the style inherits the parent configuration it is a command line4465 // configuration, which wants to inherit, so we have to skip the check of the4466 // StyleName.4467 if (!Style.InheritsParentConfig && !StyleName.equals_insensitive("file")) {4468 if (!getPredefinedStyle(StyleName, Style.Language, &Style))4469 return make_string_error("Invalid value for -style");4470 if (!Style.InheritsParentConfig)4471 return Style;4472 }4473 4474 SmallString<128> Path(FileName);4475 if (std::error_code EC = FS->makeAbsolute(Path))4476 return make_string_error(EC.message());4477 4478 // Reset possible inheritance4479 Style.InheritsParentConfig = false;4480 4481 auto dropDiagnosticHandler = [](const llvm::SMDiagnostic &, void *) {};4482 4483 auto applyChildFormatTexts = [&](FormatStyle *Style) {4484 for (const auto &MemBuf : llvm::reverse(ChildFormatTextToApply)) {4485 auto EC =4486 parseConfiguration(*MemBuf, Style, AllowUnknownOptions,4487 DiagHandler ? DiagHandler : dropDiagnosticHandler);4488 // It was already correctly parsed.4489 assert(!EC);4490 static_cast<void>(EC);4491 }4492 };4493 4494 // Look for .clang-format/_clang-format file in the file's parent directories.4495 SmallVector<std::string, 2> FilesToLookFor;4496 FilesToLookFor.push_back(".clang-format");4497 FilesToLookFor.push_back("_clang-format");4498 4499 SmallString<128> UnsuitableConfigFiles;4500 for (StringRef Directory = Path; !Directory.empty();4501 Directory = llvm::sys::path::parent_path(Directory)) {4502 auto Status = FS->status(Directory);4503 if (!Status ||4504 Status->getType() != llvm::sys::fs::file_type::directory_file) {4505 continue;4506 }4507 4508 for (const auto &F : FilesToLookFor) {4509 SmallString<128> ConfigFile(Directory);4510 4511 llvm::sys::path::append(ConfigFile, F);4512 LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");4513 4514 Status = FS->status(ConfigFile);4515 if (!Status ||4516 Status->getType() != llvm::sys::fs::file_type::regular_file) {4517 continue;4518 }4519 4520 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =4521 loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions,4522 DiagHandler, IsDotHFile);4523 if (auto EC = Text.getError()) {4524 if (EC != ParseError::Unsuitable) {4525 return make_string_error("Error reading " + ConfigFile + ": " +4526 EC.message());4527 }4528 if (!UnsuitableConfigFiles.empty())4529 UnsuitableConfigFiles.append(", ");4530 UnsuitableConfigFiles.append(ConfigFile);4531 continue;4532 }4533 4534 LLVM_DEBUG(llvm::dbgs()4535 << "Using configuration file " << ConfigFile << "\n");4536 4537 if (!Style.InheritsParentConfig) {4538 if (!ChildFormatTextToApply.empty()) {4539 LLVM_DEBUG(llvm::dbgs() << "Applying child configurations\n");4540 applyChildFormatTexts(&Style);4541 }4542 return Style;4543 }4544 4545 LLVM_DEBUG(llvm::dbgs() << "Inherits parent configuration\n");4546 4547 // Reset inheritance of style4548 Style.InheritsParentConfig = false;4549 4550 ChildFormatTextToApply.emplace_back(std::move(*Text));4551 4552 // Breaking out of the inner loop, since we don't want to parse4553 // .clang-format AND _clang-format, if both exist. Then we continue the4554 // outer loop (parent directories) in search for the parent4555 // configuration.4556 break;4557 }4558 }4559 4560 if (!UnsuitableConfigFiles.empty()) {4561 return make_string_error("Configuration file(s) do(es) not support " +4562 getLanguageName(Style.Language) + ": " +4563 UnsuitableConfigFiles);4564 }4565 4566 if (!ChildFormatTextToApply.empty()) {4567 LLVM_DEBUG(llvm::dbgs()4568 << "Applying child configurations on fallback style\n");4569 applyChildFormatTexts(&FallbackStyle);4570 }4571 4572 return FallbackStyle;4573}4574 4575static bool isClangFormatOnOff(StringRef Comment, bool On) {4576 if (Comment == (On ? "/* clang-format on */" : "/* clang-format off */"))4577 return true;4578 4579 static const char ClangFormatOn[] = "// clang-format on";4580 static const char ClangFormatOff[] = "// clang-format off";4581 const unsigned Size = (On ? sizeof ClangFormatOn : sizeof ClangFormatOff) - 1;4582 4583 return Comment.starts_with(On ? ClangFormatOn : ClangFormatOff) &&4584 (Comment.size() == Size || Comment[Size] == ':');4585}4586 4587bool isClangFormatOn(StringRef Comment) {4588 return isClangFormatOnOff(Comment, /*On=*/true);4589}4590 4591bool isClangFormatOff(StringRef Comment) {4592 return isClangFormatOnOff(Comment, /*On=*/false);4593}4594 4595} // namespace format4596} // namespace clang4597