brintos

brintos / llvm-project-archived public Read only

0
0
Text · 183.8 KiB · f0e9aff Raw
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