10b57cec5SDimitry Andric //===--- Format.cpp - Format C++ code -------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric /// 90b57cec5SDimitry Andric /// \file 100b57cec5SDimitry Andric /// This file implements functions declared in Format.h. This will be 110b57cec5SDimitry Andric /// split into separate files as we go. 120b57cec5SDimitry Andric /// 130b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #include "clang/Format/Format.h" 1604eeddc0SDimitry Andric #include "DefinitionBlockSeparator.h" 17bdd1243dSDimitry Andric #include "IntegerLiteralSeparatorFixer.h" 180b57cec5SDimitry Andric #include "NamespaceEndCommentsFixer.h" 195f757f3fSDimitry Andric #include "ObjCPropertyAttributeOrderFixer.h" 20349cc55cSDimitry Andric #include "QualifierAlignmentFixer.h" 210b57cec5SDimitry Andric #include "SortJavaScriptImports.h" 220b57cec5SDimitry Andric #include "UnwrappedLineFormatter.h" 230b57cec5SDimitry Andric #include "UsingDeclarationsSorter.h" 240b57cec5SDimitry Andric #include "clang/Tooling/Inclusions/HeaderIncludes.h" 2581ad6265SDimitry Andric #include "llvm/ADT/Sequence.h" 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric #define DEBUG_TYPE "format-formatter" 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric using clang::format::FormatStyle; 300b57cec5SDimitry Andric 31*0fca6ea1SDimitry Andric LLVM_YAML_IS_SEQUENCE_VECTOR(FormatStyle::RawStringFormat) 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric namespace llvm { 340b57cec5SDimitry Andric namespace yaml { 355f757f3fSDimitry Andric template <> 365f757f3fSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::BreakBeforeNoexceptSpecifierStyle> { 375f757f3fSDimitry Andric static void 385f757f3fSDimitry Andric enumeration(IO &IO, FormatStyle::BreakBeforeNoexceptSpecifierStyle &Value) { 395f757f3fSDimitry Andric IO.enumCase(Value, "Never", FormatStyle::BBNSS_Never); 405f757f3fSDimitry Andric IO.enumCase(Value, "OnlyWithParen", FormatStyle::BBNSS_OnlyWithParen); 415f757f3fSDimitry Andric IO.enumCase(Value, "Always", FormatStyle::BBNSS_Always); 425f757f3fSDimitry Andric } 435f757f3fSDimitry Andric }; 445f757f3fSDimitry Andric 4581ad6265SDimitry Andric template <> struct MappingTraits<FormatStyle::AlignConsecutiveStyle> { 4681ad6265SDimitry Andric static void enumInput(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) { 4781ad6265SDimitry Andric IO.enumCase(Value, "None", 4881ad6265SDimitry Andric FormatStyle::AlignConsecutiveStyle( 4981ad6265SDimitry Andric {/*Enabled=*/false, /*AcrossEmptyLines=*/false, 5081ad6265SDimitry Andric /*AcrossComments=*/false, /*AlignCompound=*/false, 51297eecfbSDimitry Andric /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); 5281ad6265SDimitry Andric IO.enumCase(Value, "Consecutive", 5381ad6265SDimitry Andric FormatStyle::AlignConsecutiveStyle( 5481ad6265SDimitry Andric {/*Enabled=*/true, /*AcrossEmptyLines=*/false, 5581ad6265SDimitry Andric /*AcrossComments=*/false, /*AlignCompound=*/false, 56297eecfbSDimitry Andric /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); 5781ad6265SDimitry Andric IO.enumCase(Value, "AcrossEmptyLines", 5881ad6265SDimitry Andric FormatStyle::AlignConsecutiveStyle( 5981ad6265SDimitry Andric {/*Enabled=*/true, /*AcrossEmptyLines=*/true, 6081ad6265SDimitry Andric /*AcrossComments=*/false, /*AlignCompound=*/false, 61297eecfbSDimitry Andric /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); 6281ad6265SDimitry Andric IO.enumCase(Value, "AcrossComments", 63297eecfbSDimitry Andric FormatStyle::AlignConsecutiveStyle( 64297eecfbSDimitry Andric {/*Enabled=*/true, /*AcrossEmptyLines=*/false, 65297eecfbSDimitry Andric /*AcrossComments=*/true, /*AlignCompound=*/false, 66297eecfbSDimitry Andric /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); 67e8d8bef9SDimitry Andric IO.enumCase(Value, "AcrossEmptyLinesAndComments", 68297eecfbSDimitry Andric FormatStyle::AlignConsecutiveStyle( 69297eecfbSDimitry Andric {/*Enabled=*/true, /*AcrossEmptyLines=*/true, 70297eecfbSDimitry Andric /*AcrossComments=*/true, /*AlignCompound=*/false, 71297eecfbSDimitry Andric /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); 72e8d8bef9SDimitry Andric 73349cc55cSDimitry Andric // For backward compatibility. 7481ad6265SDimitry Andric IO.enumCase(Value, "true", 7581ad6265SDimitry Andric FormatStyle::AlignConsecutiveStyle( 7681ad6265SDimitry Andric {/*Enabled=*/true, /*AcrossEmptyLines=*/false, 7781ad6265SDimitry Andric /*AcrossComments=*/false, /*AlignCompound=*/false, 78297eecfbSDimitry Andric /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); 7981ad6265SDimitry Andric IO.enumCase(Value, "false", 8081ad6265SDimitry Andric FormatStyle::AlignConsecutiveStyle( 8181ad6265SDimitry Andric {/*Enabled=*/false, /*AcrossEmptyLines=*/false, 8281ad6265SDimitry Andric /*AcrossComments=*/false, /*AlignCompound=*/false, 83297eecfbSDimitry Andric /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); 8481ad6265SDimitry Andric } 8581ad6265SDimitry Andric 8681ad6265SDimitry Andric static void mapping(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) { 8781ad6265SDimitry Andric IO.mapOptional("Enabled", Value.Enabled); 8881ad6265SDimitry Andric IO.mapOptional("AcrossEmptyLines", Value.AcrossEmptyLines); 8981ad6265SDimitry Andric IO.mapOptional("AcrossComments", Value.AcrossComments); 9081ad6265SDimitry Andric IO.mapOptional("AlignCompound", Value.AlignCompound); 91297eecfbSDimitry Andric IO.mapOptional("AlignFunctionPointers", Value.AlignFunctionPointers); 9281ad6265SDimitry Andric IO.mapOptional("PadOperators", Value.PadOperators); 93e8d8bef9SDimitry Andric } 94e8d8bef9SDimitry Andric }; 95e8d8bef9SDimitry Andric 96fe6060f1SDimitry Andric template <> 9706c3fb27SDimitry Andric struct MappingTraits<FormatStyle::ShortCaseStatementsAlignmentStyle> { 9806c3fb27SDimitry Andric static void mapping(IO &IO, 9906c3fb27SDimitry Andric FormatStyle::ShortCaseStatementsAlignmentStyle &Value) { 10006c3fb27SDimitry Andric IO.mapOptional("Enabled", Value.Enabled); 10106c3fb27SDimitry Andric IO.mapOptional("AcrossEmptyLines", Value.AcrossEmptyLines); 10206c3fb27SDimitry Andric IO.mapOptional("AcrossComments", Value.AcrossComments); 103*0fca6ea1SDimitry Andric IO.mapOptional("AlignCaseArrows", Value.AlignCaseArrows); 10406c3fb27SDimitry Andric IO.mapOptional("AlignCaseColons", Value.AlignCaseColons); 10506c3fb27SDimitry Andric } 10606c3fb27SDimitry Andric }; 10706c3fb27SDimitry Andric 10806c3fb27SDimitry Andric template <> 109bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::AttributeBreakingStyle> { 110bdd1243dSDimitry Andric static void enumeration(IO &IO, FormatStyle::AttributeBreakingStyle &Value) { 111bdd1243dSDimitry Andric IO.enumCase(Value, "Always", FormatStyle::ABS_Always); 112bdd1243dSDimitry Andric IO.enumCase(Value, "Leave", FormatStyle::ABS_Leave); 113bdd1243dSDimitry Andric IO.enumCase(Value, "Never", FormatStyle::ABS_Never); 114bdd1243dSDimitry Andric } 115bdd1243dSDimitry Andric }; 116bdd1243dSDimitry Andric 117bdd1243dSDimitry Andric template <> 118fe6060f1SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::ArrayInitializerAlignmentStyle> { 119fe6060f1SDimitry Andric static void enumeration(IO &IO, 120fe6060f1SDimitry Andric FormatStyle::ArrayInitializerAlignmentStyle &Value) { 121fe6060f1SDimitry Andric IO.enumCase(Value, "None", FormatStyle::AIAS_None); 122fe6060f1SDimitry Andric IO.enumCase(Value, "Left", FormatStyle::AIAS_Left); 123fe6060f1SDimitry Andric IO.enumCase(Value, "Right", FormatStyle::AIAS_Right); 124fe6060f1SDimitry Andric } 125fe6060f1SDimitry Andric }; 126fe6060f1SDimitry Andric 127bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::BinaryOperatorStyle> { 128bdd1243dSDimitry Andric static void enumeration(IO &IO, FormatStyle::BinaryOperatorStyle &Value) { 129bdd1243dSDimitry Andric IO.enumCase(Value, "All", FormatStyle::BOS_All); 130bdd1243dSDimitry Andric IO.enumCase(Value, "true", FormatStyle::BOS_All); 131bdd1243dSDimitry Andric IO.enumCase(Value, "None", FormatStyle::BOS_None); 132bdd1243dSDimitry Andric IO.enumCase(Value, "false", FormatStyle::BOS_None); 133bdd1243dSDimitry Andric IO.enumCase(Value, "NonAssignment", FormatStyle::BOS_NonAssignment); 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric }; 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::BinPackStyle> { 1380b57cec5SDimitry Andric static void enumeration(IO &IO, FormatStyle::BinPackStyle &Value) { 1390b57cec5SDimitry Andric IO.enumCase(Value, "Auto", FormatStyle::BPS_Auto); 1400b57cec5SDimitry Andric IO.enumCase(Value, "Always", FormatStyle::BPS_Always); 1410b57cec5SDimitry Andric IO.enumCase(Value, "Never", FormatStyle::BPS_Never); 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric }; 1440b57cec5SDimitry Andric 145bdd1243dSDimitry Andric template <> 146bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::BitFieldColonSpacingStyle> { 147bdd1243dSDimitry Andric static void enumeration(IO &IO, 148bdd1243dSDimitry Andric FormatStyle::BitFieldColonSpacingStyle &Value) { 149bdd1243dSDimitry Andric IO.enumCase(Value, "Both", FormatStyle::BFCS_Both); 150bdd1243dSDimitry Andric IO.enumCase(Value, "None", FormatStyle::BFCS_None); 151bdd1243dSDimitry Andric IO.enumCase(Value, "Before", FormatStyle::BFCS_Before); 152bdd1243dSDimitry Andric IO.enumCase(Value, "After", FormatStyle::BFCS_After); 1530b57cec5SDimitry Andric } 1540b57cec5SDimitry Andric }; 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> { 1570b57cec5SDimitry Andric static void enumeration(IO &IO, FormatStyle::BraceBreakingStyle &Value) { 1580b57cec5SDimitry Andric IO.enumCase(Value, "Attach", FormatStyle::BS_Attach); 1590b57cec5SDimitry Andric IO.enumCase(Value, "Linux", FormatStyle::BS_Linux); 1600b57cec5SDimitry Andric IO.enumCase(Value, "Mozilla", FormatStyle::BS_Mozilla); 1610b57cec5SDimitry Andric IO.enumCase(Value, "Stroustrup", FormatStyle::BS_Stroustrup); 1620b57cec5SDimitry Andric IO.enumCase(Value, "Allman", FormatStyle::BS_Allman); 163a7dea167SDimitry Andric IO.enumCase(Value, "Whitesmiths", FormatStyle::BS_Whitesmiths); 1640b57cec5SDimitry Andric IO.enumCase(Value, "GNU", FormatStyle::BS_GNU); 1650b57cec5SDimitry Andric IO.enumCase(Value, "WebKit", FormatStyle::BS_WebKit); 1660b57cec5SDimitry Andric IO.enumCase(Value, "Custom", FormatStyle::BS_Custom); 1670b57cec5SDimitry Andric } 1680b57cec5SDimitry Andric }; 1690b57cec5SDimitry Andric 170bdd1243dSDimitry Andric template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> { 171bdd1243dSDimitry Andric static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping) { 172bdd1243dSDimitry Andric IO.mapOptional("AfterCaseLabel", Wrapping.AfterCaseLabel); 173bdd1243dSDimitry Andric IO.mapOptional("AfterClass", Wrapping.AfterClass); 174bdd1243dSDimitry Andric IO.mapOptional("AfterControlStatement", Wrapping.AfterControlStatement); 175bdd1243dSDimitry Andric IO.mapOptional("AfterEnum", Wrapping.AfterEnum); 176bdd1243dSDimitry Andric IO.mapOptional("AfterExternBlock", Wrapping.AfterExternBlock); 177bdd1243dSDimitry Andric IO.mapOptional("AfterFunction", Wrapping.AfterFunction); 178bdd1243dSDimitry Andric IO.mapOptional("AfterNamespace", Wrapping.AfterNamespace); 179bdd1243dSDimitry Andric IO.mapOptional("AfterObjCDeclaration", Wrapping.AfterObjCDeclaration); 180bdd1243dSDimitry Andric IO.mapOptional("AfterStruct", Wrapping.AfterStruct); 181bdd1243dSDimitry Andric IO.mapOptional("AfterUnion", Wrapping.AfterUnion); 182bdd1243dSDimitry Andric IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch); 183bdd1243dSDimitry Andric IO.mapOptional("BeforeElse", Wrapping.BeforeElse); 184bdd1243dSDimitry Andric IO.mapOptional("BeforeLambdaBody", Wrapping.BeforeLambdaBody); 185bdd1243dSDimitry Andric IO.mapOptional("BeforeWhile", Wrapping.BeforeWhile); 186bdd1243dSDimitry Andric IO.mapOptional("IndentBraces", Wrapping.IndentBraces); 187bdd1243dSDimitry Andric IO.mapOptional("SplitEmptyFunction", Wrapping.SplitEmptyFunction); 188bdd1243dSDimitry Andric IO.mapOptional("SplitEmptyRecord", Wrapping.SplitEmptyRecord); 189bdd1243dSDimitry Andric IO.mapOptional("SplitEmptyNamespace", Wrapping.SplitEmptyNamespace); 190bdd1243dSDimitry Andric } 191bdd1243dSDimitry Andric }; 192bdd1243dSDimitry Andric 193bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::BracketAlignmentStyle> { 194bdd1243dSDimitry Andric static void enumeration(IO &IO, FormatStyle::BracketAlignmentStyle &Value) { 195bdd1243dSDimitry Andric IO.enumCase(Value, "Align", FormatStyle::BAS_Align); 196bdd1243dSDimitry Andric IO.enumCase(Value, "DontAlign", FormatStyle::BAS_DontAlign); 197bdd1243dSDimitry Andric IO.enumCase(Value, "AlwaysBreak", FormatStyle::BAS_AlwaysBreak); 198bdd1243dSDimitry Andric IO.enumCase(Value, "BlockIndent", FormatStyle::BAS_BlockIndent); 199bdd1243dSDimitry Andric 200bdd1243dSDimitry Andric // For backward compatibility. 201bdd1243dSDimitry Andric IO.enumCase(Value, "true", FormatStyle::BAS_Align); 202bdd1243dSDimitry Andric IO.enumCase(Value, "false", FormatStyle::BAS_DontAlign); 203bdd1243dSDimitry Andric } 204bdd1243dSDimitry Andric }; 205bdd1243dSDimitry Andric 2060b57cec5SDimitry Andric template <> 207a7dea167SDimitry Andric struct ScalarEnumerationTraits< 208a7dea167SDimitry Andric FormatStyle::BraceWrappingAfterControlStatementStyle> { 209a7dea167SDimitry Andric static void 210a7dea167SDimitry Andric enumeration(IO &IO, 211a7dea167SDimitry Andric FormatStyle::BraceWrappingAfterControlStatementStyle &Value) { 212a7dea167SDimitry Andric IO.enumCase(Value, "Never", FormatStyle::BWACS_Never); 213a7dea167SDimitry Andric IO.enumCase(Value, "MultiLine", FormatStyle::BWACS_MultiLine); 214a7dea167SDimitry Andric IO.enumCase(Value, "Always", FormatStyle::BWACS_Always); 2155ffd83dbSDimitry Andric 2165ffd83dbSDimitry Andric // For backward compatibility. 2175ffd83dbSDimitry Andric IO.enumCase(Value, "false", FormatStyle::BWACS_Never); 2185ffd83dbSDimitry Andric IO.enumCase(Value, "true", FormatStyle::BWACS_Always); 219a7dea167SDimitry Andric } 220a7dea167SDimitry Andric }; 221a7dea167SDimitry Andric 222a7dea167SDimitry Andric template <> 22381ad6265SDimitry Andric struct ScalarEnumerationTraits< 22481ad6265SDimitry Andric FormatStyle::BreakBeforeConceptDeclarationsStyle> { 22581ad6265SDimitry Andric static void 22681ad6265SDimitry Andric enumeration(IO &IO, FormatStyle::BreakBeforeConceptDeclarationsStyle &Value) { 22781ad6265SDimitry Andric IO.enumCase(Value, "Never", FormatStyle::BBCDS_Never); 22881ad6265SDimitry Andric IO.enumCase(Value, "Allowed", FormatStyle::BBCDS_Allowed); 22981ad6265SDimitry Andric IO.enumCase(Value, "Always", FormatStyle::BBCDS_Always); 23081ad6265SDimitry Andric 23181ad6265SDimitry Andric // For backward compatibility. 23281ad6265SDimitry Andric IO.enumCase(Value, "true", FormatStyle::BBCDS_Always); 23381ad6265SDimitry Andric IO.enumCase(Value, "false", FormatStyle::BBCDS_Allowed); 23481ad6265SDimitry Andric } 23581ad6265SDimitry Andric }; 23681ad6265SDimitry Andric 23781ad6265SDimitry Andric template <> 238bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::BreakBeforeInlineASMColonStyle> { 239bdd1243dSDimitry Andric static void enumeration(IO &IO, 240bdd1243dSDimitry Andric FormatStyle::BreakBeforeInlineASMColonStyle &Value) { 241bdd1243dSDimitry Andric IO.enumCase(Value, "Never", FormatStyle::BBIAS_Never); 242bdd1243dSDimitry Andric IO.enumCase(Value, "OnlyMultiline", FormatStyle::BBIAS_OnlyMultiline); 243bdd1243dSDimitry Andric IO.enumCase(Value, "Always", FormatStyle::BBIAS_Always); 244bdd1243dSDimitry Andric } 245bdd1243dSDimitry Andric }; 2465f757f3fSDimitry Andric 247bdd1243dSDimitry Andric template <> 2480b57cec5SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> { 2490b57cec5SDimitry Andric static void 2500b57cec5SDimitry Andric enumeration(IO &IO, FormatStyle::BreakConstructorInitializersStyle &Value) { 2510b57cec5SDimitry Andric IO.enumCase(Value, "BeforeColon", FormatStyle::BCIS_BeforeColon); 2520b57cec5SDimitry Andric IO.enumCase(Value, "BeforeComma", FormatStyle::BCIS_BeforeComma); 2530b57cec5SDimitry Andric IO.enumCase(Value, "AfterColon", FormatStyle::BCIS_AfterColon); 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric }; 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric template <> 2580b57cec5SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::BreakInheritanceListStyle> { 2590b57cec5SDimitry Andric static void enumeration(IO &IO, 2600b57cec5SDimitry Andric FormatStyle::BreakInheritanceListStyle &Value) { 2610b57cec5SDimitry Andric IO.enumCase(Value, "BeforeColon", FormatStyle::BILS_BeforeColon); 2620b57cec5SDimitry Andric IO.enumCase(Value, "BeforeComma", FormatStyle::BILS_BeforeComma); 2630b57cec5SDimitry Andric IO.enumCase(Value, "AfterColon", FormatStyle::BILS_AfterColon); 264fe6060f1SDimitry Andric IO.enumCase(Value, "AfterComma", FormatStyle::BILS_AfterComma); 265fe6060f1SDimitry Andric } 266fe6060f1SDimitry Andric }; 267fe6060f1SDimitry Andric 268fe6060f1SDimitry Andric template <> 2690b57cec5SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::BreakTemplateDeclarationsStyle> { 2700b57cec5SDimitry Andric static void enumeration(IO &IO, 2710b57cec5SDimitry Andric FormatStyle::BreakTemplateDeclarationsStyle &Value) { 272*0fca6ea1SDimitry Andric IO.enumCase(Value, "Leave", FormatStyle::BTDS_Leave); 2730b57cec5SDimitry Andric IO.enumCase(Value, "No", FormatStyle::BTDS_No); 2740b57cec5SDimitry Andric IO.enumCase(Value, "MultiLine", FormatStyle::BTDS_MultiLine); 2750b57cec5SDimitry Andric IO.enumCase(Value, "Yes", FormatStyle::BTDS_Yes); 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andric // For backward compatibility. 2780b57cec5SDimitry Andric IO.enumCase(Value, "false", FormatStyle::BTDS_MultiLine); 2790b57cec5SDimitry Andric IO.enumCase(Value, "true", FormatStyle::BTDS_Yes); 2800b57cec5SDimitry Andric } 2810b57cec5SDimitry Andric }; 2820b57cec5SDimitry Andric 283*0fca6ea1SDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::DAGArgStyle> { 284*0fca6ea1SDimitry Andric static void enumeration(IO &IO, FormatStyle::DAGArgStyle &Value) { 285*0fca6ea1SDimitry Andric IO.enumCase(Value, "DontBreak", FormatStyle::DAS_DontBreak); 286*0fca6ea1SDimitry Andric IO.enumCase(Value, "BreakElements", FormatStyle::DAS_BreakElements); 287*0fca6ea1SDimitry Andric IO.enumCase(Value, "BreakAll", FormatStyle::DAS_BreakAll); 288*0fca6ea1SDimitry Andric } 289*0fca6ea1SDimitry Andric }; 290*0fca6ea1SDimitry Andric 2910b57cec5SDimitry Andric template <> 2920b57cec5SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> { 2930b57cec5SDimitry Andric static void 2940b57cec5SDimitry Andric enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) { 2950b57cec5SDimitry Andric IO.enumCase(Value, "None", FormatStyle::DRTBS_None); 2960b57cec5SDimitry Andric IO.enumCase(Value, "All", FormatStyle::DRTBS_All); 2970b57cec5SDimitry Andric IO.enumCase(Value, "TopLevel", FormatStyle::DRTBS_TopLevel); 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric // For backward compatibility. 3000b57cec5SDimitry Andric IO.enumCase(Value, "false", FormatStyle::DRTBS_None); 3010b57cec5SDimitry Andric IO.enumCase(Value, "true", FormatStyle::DRTBS_All); 3020b57cec5SDimitry Andric } 3030b57cec5SDimitry Andric }; 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric template <> 3060b57cec5SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::EscapedNewlineAlignmentStyle> { 3070b57cec5SDimitry Andric static void enumeration(IO &IO, 3080b57cec5SDimitry Andric FormatStyle::EscapedNewlineAlignmentStyle &Value) { 3090b57cec5SDimitry Andric IO.enumCase(Value, "DontAlign", FormatStyle::ENAS_DontAlign); 3100b57cec5SDimitry Andric IO.enumCase(Value, "Left", FormatStyle::ENAS_Left); 311*0fca6ea1SDimitry Andric IO.enumCase(Value, "LeftWithLastLine", FormatStyle::ENAS_LeftWithLastLine); 3120b57cec5SDimitry Andric IO.enumCase(Value, "Right", FormatStyle::ENAS_Right); 3130b57cec5SDimitry Andric 3140b57cec5SDimitry Andric // For backward compatibility. 3150b57cec5SDimitry Andric IO.enumCase(Value, "true", FormatStyle::ENAS_Left); 3160b57cec5SDimitry Andric IO.enumCase(Value, "false", FormatStyle::ENAS_Right); 3170b57cec5SDimitry Andric } 3180b57cec5SDimitry Andric }; 3190b57cec5SDimitry Andric 320bdd1243dSDimitry Andric template <> 321bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::EmptyLineAfterAccessModifierStyle> { 322bdd1243dSDimitry Andric static void 323bdd1243dSDimitry Andric enumeration(IO &IO, FormatStyle::EmptyLineAfterAccessModifierStyle &Value) { 324bdd1243dSDimitry Andric IO.enumCase(Value, "Never", FormatStyle::ELAAMS_Never); 325bdd1243dSDimitry Andric IO.enumCase(Value, "Leave", FormatStyle::ELAAMS_Leave); 326bdd1243dSDimitry Andric IO.enumCase(Value, "Always", FormatStyle::ELAAMS_Always); 327bdd1243dSDimitry Andric } 328bdd1243dSDimitry Andric }; 329bdd1243dSDimitry Andric 330bdd1243dSDimitry Andric template <> 331bdd1243dSDimitry Andric struct ScalarEnumerationTraits< 332bdd1243dSDimitry Andric FormatStyle::EmptyLineBeforeAccessModifierStyle> { 333bdd1243dSDimitry Andric static void 334bdd1243dSDimitry Andric enumeration(IO &IO, FormatStyle::EmptyLineBeforeAccessModifierStyle &Value) { 335bdd1243dSDimitry Andric IO.enumCase(Value, "Never", FormatStyle::ELBAMS_Never); 336bdd1243dSDimitry Andric IO.enumCase(Value, "Leave", FormatStyle::ELBAMS_Leave); 337bdd1243dSDimitry Andric IO.enumCase(Value, "LogicalBlock", FormatStyle::ELBAMS_LogicalBlock); 338bdd1243dSDimitry Andric IO.enumCase(Value, "Always", FormatStyle::ELBAMS_Always); 339bdd1243dSDimitry Andric } 340bdd1243dSDimitry Andric }; 341bdd1243dSDimitry Andric 342bdd1243dSDimitry Andric template <> 343bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::IndentExternBlockStyle> { 344bdd1243dSDimitry Andric static void enumeration(IO &IO, FormatStyle::IndentExternBlockStyle &Value) { 345bdd1243dSDimitry Andric IO.enumCase(Value, "AfterExternBlock", FormatStyle::IEBS_AfterExternBlock); 346bdd1243dSDimitry Andric IO.enumCase(Value, "Indent", FormatStyle::IEBS_Indent); 347bdd1243dSDimitry Andric IO.enumCase(Value, "NoIndent", FormatStyle::IEBS_NoIndent); 348bdd1243dSDimitry Andric IO.enumCase(Value, "true", FormatStyle::IEBS_Indent); 349bdd1243dSDimitry Andric IO.enumCase(Value, "false", FormatStyle::IEBS_NoIndent); 350bdd1243dSDimitry Andric } 351bdd1243dSDimitry Andric }; 352bdd1243dSDimitry Andric 353bdd1243dSDimitry Andric template <> struct MappingTraits<FormatStyle::IntegerLiteralSeparatorStyle> { 354bdd1243dSDimitry Andric static void mapping(IO &IO, FormatStyle::IntegerLiteralSeparatorStyle &Base) { 355bdd1243dSDimitry Andric IO.mapOptional("Binary", Base.Binary); 3561ac55f4cSDimitry Andric IO.mapOptional("BinaryMinDigits", Base.BinaryMinDigits); 357bdd1243dSDimitry Andric IO.mapOptional("Decimal", Base.Decimal); 3581ac55f4cSDimitry Andric IO.mapOptional("DecimalMinDigits", Base.DecimalMinDigits); 359bdd1243dSDimitry Andric IO.mapOptional("Hex", Base.Hex); 3601ac55f4cSDimitry Andric IO.mapOptional("HexMinDigits", Base.HexMinDigits); 361bdd1243dSDimitry Andric } 362bdd1243dSDimitry Andric }; 363bdd1243dSDimitry Andric 364bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::JavaScriptQuoteStyle> { 365bdd1243dSDimitry Andric static void enumeration(IO &IO, FormatStyle::JavaScriptQuoteStyle &Value) { 366bdd1243dSDimitry Andric IO.enumCase(Value, "Leave", FormatStyle::JSQS_Leave); 367bdd1243dSDimitry Andric IO.enumCase(Value, "Single", FormatStyle::JSQS_Single); 368bdd1243dSDimitry Andric IO.enumCase(Value, "Double", FormatStyle::JSQS_Double); 369bdd1243dSDimitry Andric } 370bdd1243dSDimitry Andric }; 371bdd1243dSDimitry Andric 372*0fca6ea1SDimitry Andric template <> struct MappingTraits<FormatStyle::KeepEmptyLinesStyle> { 373*0fca6ea1SDimitry Andric static void mapping(IO &IO, FormatStyle::KeepEmptyLinesStyle &Value) { 374*0fca6ea1SDimitry Andric IO.mapOptional("AtEndOfFile", Value.AtEndOfFile); 375*0fca6ea1SDimitry Andric IO.mapOptional("AtStartOfBlock", Value.AtStartOfBlock); 376*0fca6ea1SDimitry Andric IO.mapOptional("AtStartOfFile", Value.AtStartOfFile); 377*0fca6ea1SDimitry Andric } 378*0fca6ea1SDimitry Andric }; 379*0fca6ea1SDimitry Andric 380bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> { 381bdd1243dSDimitry Andric static void enumeration(IO &IO, FormatStyle::LanguageKind &Value) { 382bdd1243dSDimitry Andric IO.enumCase(Value, "Cpp", FormatStyle::LK_Cpp); 383bdd1243dSDimitry Andric IO.enumCase(Value, "Java", FormatStyle::LK_Java); 384bdd1243dSDimitry Andric IO.enumCase(Value, "JavaScript", FormatStyle::LK_JavaScript); 385bdd1243dSDimitry Andric IO.enumCase(Value, "ObjC", FormatStyle::LK_ObjC); 386bdd1243dSDimitry Andric IO.enumCase(Value, "Proto", FormatStyle::LK_Proto); 387bdd1243dSDimitry Andric IO.enumCase(Value, "TableGen", FormatStyle::LK_TableGen); 388bdd1243dSDimitry Andric IO.enumCase(Value, "TextProto", FormatStyle::LK_TextProto); 389bdd1243dSDimitry Andric IO.enumCase(Value, "CSharp", FormatStyle::LK_CSharp); 390bdd1243dSDimitry Andric IO.enumCase(Value, "Json", FormatStyle::LK_Json); 39106c3fb27SDimitry Andric IO.enumCase(Value, "Verilog", FormatStyle::LK_Verilog); 392bdd1243dSDimitry Andric } 393bdd1243dSDimitry Andric }; 394bdd1243dSDimitry Andric 395bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::LanguageStandard> { 396bdd1243dSDimitry Andric static void enumeration(IO &IO, FormatStyle::LanguageStandard &Value) { 397bdd1243dSDimitry Andric IO.enumCase(Value, "c++03", FormatStyle::LS_Cpp03); 398bdd1243dSDimitry Andric IO.enumCase(Value, "C++03", FormatStyle::LS_Cpp03); // Legacy alias 399bdd1243dSDimitry Andric IO.enumCase(Value, "Cpp03", FormatStyle::LS_Cpp03); // Legacy alias 400bdd1243dSDimitry Andric 401bdd1243dSDimitry Andric IO.enumCase(Value, "c++11", FormatStyle::LS_Cpp11); 402bdd1243dSDimitry Andric IO.enumCase(Value, "C++11", FormatStyle::LS_Cpp11); // Legacy alias 403bdd1243dSDimitry Andric 404bdd1243dSDimitry Andric IO.enumCase(Value, "c++14", FormatStyle::LS_Cpp14); 405bdd1243dSDimitry Andric IO.enumCase(Value, "c++17", FormatStyle::LS_Cpp17); 406bdd1243dSDimitry Andric IO.enumCase(Value, "c++20", FormatStyle::LS_Cpp20); 407bdd1243dSDimitry Andric 408bdd1243dSDimitry Andric IO.enumCase(Value, "Latest", FormatStyle::LS_Latest); 409bdd1243dSDimitry Andric IO.enumCase(Value, "Cpp11", FormatStyle::LS_Latest); // Legacy alias 410bdd1243dSDimitry Andric IO.enumCase(Value, "Auto", FormatStyle::LS_Auto); 411bdd1243dSDimitry Andric } 412bdd1243dSDimitry Andric }; 413bdd1243dSDimitry Andric 414bdd1243dSDimitry Andric template <> 415bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::LambdaBodyIndentationKind> { 416bdd1243dSDimitry Andric static void enumeration(IO &IO, 417bdd1243dSDimitry Andric FormatStyle::LambdaBodyIndentationKind &Value) { 418bdd1243dSDimitry Andric IO.enumCase(Value, "Signature", FormatStyle::LBI_Signature); 419bdd1243dSDimitry Andric IO.enumCase(Value, "OuterScope", FormatStyle::LBI_OuterScope); 420bdd1243dSDimitry Andric } 421bdd1243dSDimitry Andric }; 422bdd1243dSDimitry Andric 423bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::LineEndingStyle> { 424bdd1243dSDimitry Andric static void enumeration(IO &IO, FormatStyle::LineEndingStyle &Value) { 425bdd1243dSDimitry Andric IO.enumCase(Value, "LF", FormatStyle::LE_LF); 426bdd1243dSDimitry Andric IO.enumCase(Value, "CRLF", FormatStyle::LE_CRLF); 427bdd1243dSDimitry Andric IO.enumCase(Value, "DeriveLF", FormatStyle::LE_DeriveLF); 428bdd1243dSDimitry Andric IO.enumCase(Value, "DeriveCRLF", FormatStyle::LE_DeriveCRLF); 429bdd1243dSDimitry Andric } 430bdd1243dSDimitry Andric }; 431bdd1243dSDimitry Andric 432bdd1243dSDimitry Andric template <> 433bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::NamespaceIndentationKind> { 434bdd1243dSDimitry Andric static void enumeration(IO &IO, 435bdd1243dSDimitry Andric FormatStyle::NamespaceIndentationKind &Value) { 436bdd1243dSDimitry Andric IO.enumCase(Value, "None", FormatStyle::NI_None); 437bdd1243dSDimitry Andric IO.enumCase(Value, "Inner", FormatStyle::NI_Inner); 438bdd1243dSDimitry Andric IO.enumCase(Value, "All", FormatStyle::NI_All); 439bdd1243dSDimitry Andric } 440bdd1243dSDimitry Andric }; 441bdd1243dSDimitry Andric 4425ffd83dbSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::OperandAlignmentStyle> { 4435ffd83dbSDimitry Andric static void enumeration(IO &IO, FormatStyle::OperandAlignmentStyle &Value) { 4445ffd83dbSDimitry Andric IO.enumCase(Value, "DontAlign", FormatStyle::OAS_DontAlign); 4455ffd83dbSDimitry Andric IO.enumCase(Value, "Align", FormatStyle::OAS_Align); 4465ffd83dbSDimitry Andric IO.enumCase(Value, "AlignAfterOperator", 4475ffd83dbSDimitry Andric FormatStyle::OAS_AlignAfterOperator); 4485ffd83dbSDimitry Andric 4495ffd83dbSDimitry Andric // For backward compatibility. 4505ffd83dbSDimitry Andric IO.enumCase(Value, "true", FormatStyle::OAS_Align); 4515ffd83dbSDimitry Andric IO.enumCase(Value, "false", FormatStyle::OAS_DontAlign); 4525ffd83dbSDimitry Andric } 4535ffd83dbSDimitry Andric }; 4545ffd83dbSDimitry Andric 455bdd1243dSDimitry Andric template <> 456bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::PackConstructorInitializersStyle> { 457bdd1243dSDimitry Andric static void 458bdd1243dSDimitry Andric enumeration(IO &IO, FormatStyle::PackConstructorInitializersStyle &Value) { 459bdd1243dSDimitry Andric IO.enumCase(Value, "Never", FormatStyle::PCIS_Never); 460bdd1243dSDimitry Andric IO.enumCase(Value, "BinPack", FormatStyle::PCIS_BinPack); 461bdd1243dSDimitry Andric IO.enumCase(Value, "CurrentLine", FormatStyle::PCIS_CurrentLine); 462bdd1243dSDimitry Andric IO.enumCase(Value, "NextLine", FormatStyle::PCIS_NextLine); 46306c3fb27SDimitry Andric IO.enumCase(Value, "NextLineOnly", FormatStyle::PCIS_NextLineOnly); 464bdd1243dSDimitry Andric } 465bdd1243dSDimitry Andric }; 466bdd1243dSDimitry Andric 4670b57cec5SDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> { 4680b57cec5SDimitry Andric static void enumeration(IO &IO, FormatStyle::PointerAlignmentStyle &Value) { 4690b57cec5SDimitry Andric IO.enumCase(Value, "Middle", FormatStyle::PAS_Middle); 4700b57cec5SDimitry Andric IO.enumCase(Value, "Left", FormatStyle::PAS_Left); 4710b57cec5SDimitry Andric IO.enumCase(Value, "Right", FormatStyle::PAS_Right); 4720b57cec5SDimitry Andric 4730b57cec5SDimitry Andric // For backward compatibility. 4740b57cec5SDimitry Andric IO.enumCase(Value, "true", FormatStyle::PAS_Left); 4750b57cec5SDimitry Andric IO.enumCase(Value, "false", FormatStyle::PAS_Right); 4760b57cec5SDimitry Andric } 4770b57cec5SDimitry Andric }; 4780b57cec5SDimitry Andric 4790b57cec5SDimitry Andric template <> 480bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::PPDirectiveIndentStyle> { 481bdd1243dSDimitry Andric static void enumeration(IO &IO, FormatStyle::PPDirectiveIndentStyle &Value) { 482bdd1243dSDimitry Andric IO.enumCase(Value, "None", FormatStyle::PPDIS_None); 483bdd1243dSDimitry Andric IO.enumCase(Value, "AfterHash", FormatStyle::PPDIS_AfterHash); 484bdd1243dSDimitry Andric IO.enumCase(Value, "BeforeHash", FormatStyle::PPDIS_BeforeHash); 48504eeddc0SDimitry Andric } 48604eeddc0SDimitry Andric }; 48704eeddc0SDimitry Andric 48804eeddc0SDimitry Andric template <> 489bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::QualifierAlignmentStyle> { 490bdd1243dSDimitry Andric static void enumeration(IO &IO, FormatStyle::QualifierAlignmentStyle &Value) { 491bdd1243dSDimitry Andric IO.enumCase(Value, "Leave", FormatStyle::QAS_Leave); 492bdd1243dSDimitry Andric IO.enumCase(Value, "Left", FormatStyle::QAS_Left); 493bdd1243dSDimitry Andric IO.enumCase(Value, "Right", FormatStyle::QAS_Right); 494bdd1243dSDimitry Andric IO.enumCase(Value, "Custom", FormatStyle::QAS_Custom); 495bdd1243dSDimitry Andric } 496bdd1243dSDimitry Andric }; 497bdd1243dSDimitry Andric 498bdd1243dSDimitry Andric template <> struct MappingTraits<FormatStyle::RawStringFormat> { 499bdd1243dSDimitry Andric static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) { 500bdd1243dSDimitry Andric IO.mapOptional("Language", Format.Language); 501bdd1243dSDimitry Andric IO.mapOptional("Delimiters", Format.Delimiters); 502bdd1243dSDimitry Andric IO.mapOptional("EnclosingFunctions", Format.EnclosingFunctions); 503bdd1243dSDimitry Andric IO.mapOptional("CanonicalDelimiter", Format.CanonicalDelimiter); 504bdd1243dSDimitry Andric IO.mapOptional("BasedOnStyle", Format.BasedOnStyle); 505e8d8bef9SDimitry Andric } 506e8d8bef9SDimitry Andric }; 507e8d8bef9SDimitry Andric 508e8d8bef9SDimitry Andric template <> 509fe6060f1SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::ReferenceAlignmentStyle> { 510fe6060f1SDimitry Andric static void enumeration(IO &IO, FormatStyle::ReferenceAlignmentStyle &Value) { 511fe6060f1SDimitry Andric IO.enumCase(Value, "Pointer", FormatStyle::RAS_Pointer); 512fe6060f1SDimitry Andric IO.enumCase(Value, "Middle", FormatStyle::RAS_Middle); 513fe6060f1SDimitry Andric IO.enumCase(Value, "Left", FormatStyle::RAS_Left); 514fe6060f1SDimitry Andric IO.enumCase(Value, "Right", FormatStyle::RAS_Right); 515fe6060f1SDimitry Andric } 516fe6060f1SDimitry Andric }; 517fe6060f1SDimitry Andric 518fe6060f1SDimitry Andric template <> 51906c3fb27SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::RemoveParenthesesStyle> { 52006c3fb27SDimitry Andric static void enumeration(IO &IO, FormatStyle::RemoveParenthesesStyle &Value) { 52106c3fb27SDimitry Andric IO.enumCase(Value, "Leave", FormatStyle::RPS_Leave); 52206c3fb27SDimitry Andric IO.enumCase(Value, "MultipleParentheses", 52306c3fb27SDimitry Andric FormatStyle::RPS_MultipleParentheses); 52406c3fb27SDimitry Andric IO.enumCase(Value, "ReturnStatement", FormatStyle::RPS_ReturnStatement); 52506c3fb27SDimitry Andric } 52606c3fb27SDimitry Andric }; 52706c3fb27SDimitry Andric 52806c3fb27SDimitry Andric template <> 52981ad6265SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::RequiresClausePositionStyle> { 53081ad6265SDimitry Andric static void enumeration(IO &IO, 53181ad6265SDimitry Andric FormatStyle::RequiresClausePositionStyle &Value) { 53281ad6265SDimitry Andric IO.enumCase(Value, "OwnLine", FormatStyle::RCPS_OwnLine); 53381ad6265SDimitry Andric IO.enumCase(Value, "WithPreceding", FormatStyle::RCPS_WithPreceding); 53481ad6265SDimitry Andric IO.enumCase(Value, "WithFollowing", FormatStyle::RCPS_WithFollowing); 53581ad6265SDimitry Andric IO.enumCase(Value, "SingleLine", FormatStyle::RCPS_SingleLine); 53681ad6265SDimitry Andric } 53781ad6265SDimitry Andric }; 53881ad6265SDimitry Andric 53981ad6265SDimitry Andric template <> 540bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::RequiresExpressionIndentationKind> { 541bdd1243dSDimitry Andric static void 542bdd1243dSDimitry Andric enumeration(IO &IO, FormatStyle::RequiresExpressionIndentationKind &Value) { 543bdd1243dSDimitry Andric IO.enumCase(Value, "Keyword", FormatStyle::REI_Keyword); 544bdd1243dSDimitry Andric IO.enumCase(Value, "OuterScope", FormatStyle::REI_OuterScope); 5450b57cec5SDimitry Andric } 5460b57cec5SDimitry Andric }; 5470b57cec5SDimitry Andric 548e8d8bef9SDimitry Andric template <> 549bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> { 550bdd1243dSDimitry Andric static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) { 551bdd1243dSDimitry Andric IO.enumCase(Value, "None", FormatStyle::RTBS_None); 552*0fca6ea1SDimitry Andric IO.enumCase(Value, "Automatic", FormatStyle::RTBS_Automatic); 553*0fca6ea1SDimitry Andric IO.enumCase(Value, "ExceptShortType", FormatStyle::RTBS_ExceptShortType); 554bdd1243dSDimitry Andric IO.enumCase(Value, "All", FormatStyle::RTBS_All); 555bdd1243dSDimitry Andric IO.enumCase(Value, "TopLevel", FormatStyle::RTBS_TopLevel); 556bdd1243dSDimitry Andric IO.enumCase(Value, "TopLevelDefinitions", 557bdd1243dSDimitry Andric FormatStyle::RTBS_TopLevelDefinitions); 558bdd1243dSDimitry Andric IO.enumCase(Value, "AllDefinitions", FormatStyle::RTBS_AllDefinitions); 559bdd1243dSDimitry Andric } 560bdd1243dSDimitry Andric }; 561bdd1243dSDimitry Andric 562bdd1243dSDimitry Andric template <> 563bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::SeparateDefinitionStyle> { 564bdd1243dSDimitry Andric static void enumeration(IO &IO, FormatStyle::SeparateDefinitionStyle &Value) { 565bdd1243dSDimitry Andric IO.enumCase(Value, "Leave", FormatStyle::SDS_Leave); 566bdd1243dSDimitry Andric IO.enumCase(Value, "Always", FormatStyle::SDS_Always); 567bdd1243dSDimitry Andric IO.enumCase(Value, "Never", FormatStyle::SDS_Never); 568bdd1243dSDimitry Andric } 569bdd1243dSDimitry Andric }; 570bdd1243dSDimitry Andric 571bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::ShortBlockStyle> { 572bdd1243dSDimitry Andric static void enumeration(IO &IO, FormatStyle::ShortBlockStyle &Value) { 573bdd1243dSDimitry Andric IO.enumCase(Value, "Never", FormatStyle::SBS_Never); 574bdd1243dSDimitry Andric IO.enumCase(Value, "false", FormatStyle::SBS_Never); 575bdd1243dSDimitry Andric IO.enumCase(Value, "Always", FormatStyle::SBS_Always); 576bdd1243dSDimitry Andric IO.enumCase(Value, "true", FormatStyle::SBS_Always); 577bdd1243dSDimitry Andric IO.enumCase(Value, "Empty", FormatStyle::SBS_Empty); 578bdd1243dSDimitry Andric } 579bdd1243dSDimitry Andric }; 580bdd1243dSDimitry Andric 581bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> { 582bdd1243dSDimitry Andric static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) { 583bdd1243dSDimitry Andric IO.enumCase(Value, "None", FormatStyle::SFS_None); 584bdd1243dSDimitry Andric IO.enumCase(Value, "false", FormatStyle::SFS_None); 585bdd1243dSDimitry Andric IO.enumCase(Value, "All", FormatStyle::SFS_All); 586bdd1243dSDimitry Andric IO.enumCase(Value, "true", FormatStyle::SFS_All); 587bdd1243dSDimitry Andric IO.enumCase(Value, "Inline", FormatStyle::SFS_Inline); 588bdd1243dSDimitry Andric IO.enumCase(Value, "InlineOnly", FormatStyle::SFS_InlineOnly); 589bdd1243dSDimitry Andric IO.enumCase(Value, "Empty", FormatStyle::SFS_Empty); 590bdd1243dSDimitry Andric } 591bdd1243dSDimitry Andric }; 592bdd1243dSDimitry Andric 593bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::ShortIfStyle> { 594bdd1243dSDimitry Andric static void enumeration(IO &IO, FormatStyle::ShortIfStyle &Value) { 595bdd1243dSDimitry Andric IO.enumCase(Value, "Never", FormatStyle::SIS_Never); 596bdd1243dSDimitry Andric IO.enumCase(Value, "WithoutElse", FormatStyle::SIS_WithoutElse); 597bdd1243dSDimitry Andric IO.enumCase(Value, "OnlyFirstIf", FormatStyle::SIS_OnlyFirstIf); 598bdd1243dSDimitry Andric IO.enumCase(Value, "AllIfsAndElse", FormatStyle::SIS_AllIfsAndElse); 599bdd1243dSDimitry Andric 600bdd1243dSDimitry Andric // For backward compatibility. 601bdd1243dSDimitry Andric IO.enumCase(Value, "Always", FormatStyle::SIS_OnlyFirstIf); 602bdd1243dSDimitry Andric IO.enumCase(Value, "false", FormatStyle::SIS_Never); 603bdd1243dSDimitry Andric IO.enumCase(Value, "true", FormatStyle::SIS_WithoutElse); 604bdd1243dSDimitry Andric } 605bdd1243dSDimitry Andric }; 606bdd1243dSDimitry Andric 607bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::ShortLambdaStyle> { 608bdd1243dSDimitry Andric static void enumeration(IO &IO, FormatStyle::ShortLambdaStyle &Value) { 609bdd1243dSDimitry Andric IO.enumCase(Value, "None", FormatStyle::SLS_None); 610bdd1243dSDimitry Andric IO.enumCase(Value, "false", FormatStyle::SLS_None); 611bdd1243dSDimitry Andric IO.enumCase(Value, "Empty", FormatStyle::SLS_Empty); 612bdd1243dSDimitry Andric IO.enumCase(Value, "Inline", FormatStyle::SLS_Inline); 613bdd1243dSDimitry Andric IO.enumCase(Value, "All", FormatStyle::SLS_All); 614bdd1243dSDimitry Andric IO.enumCase(Value, "true", FormatStyle::SLS_All); 615e8d8bef9SDimitry Andric } 616e8d8bef9SDimitry Andric }; 617e8d8bef9SDimitry Andric 618fe6060f1SDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::SortIncludesOptions> { 619fe6060f1SDimitry Andric static void enumeration(IO &IO, FormatStyle::SortIncludesOptions &Value) { 620fe6060f1SDimitry Andric IO.enumCase(Value, "Never", FormatStyle::SI_Never); 621fe6060f1SDimitry Andric IO.enumCase(Value, "CaseInsensitive", FormatStyle::SI_CaseInsensitive); 622fe6060f1SDimitry Andric IO.enumCase(Value, "CaseSensitive", FormatStyle::SI_CaseSensitive); 623fe6060f1SDimitry Andric 624fe6060f1SDimitry Andric // For backward compatibility. 625fe6060f1SDimitry Andric IO.enumCase(Value, "false", FormatStyle::SI_Never); 626fe6060f1SDimitry Andric IO.enumCase(Value, "true", FormatStyle::SI_CaseSensitive); 627fe6060f1SDimitry Andric } 628fe6060f1SDimitry Andric }; 629fe6060f1SDimitry Andric 630e8d8bef9SDimitry Andric template <> 631e8d8bef9SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::SortJavaStaticImportOptions> { 632e8d8bef9SDimitry Andric static void enumeration(IO &IO, 633e8d8bef9SDimitry Andric FormatStyle::SortJavaStaticImportOptions &Value) { 634e8d8bef9SDimitry Andric IO.enumCase(Value, "Before", FormatStyle::SJSIO_Before); 635e8d8bef9SDimitry Andric IO.enumCase(Value, "After", FormatStyle::SJSIO_After); 636e8d8bef9SDimitry Andric } 637e8d8bef9SDimitry Andric }; 638e8d8bef9SDimitry Andric 639bdd1243dSDimitry Andric template <> 640bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::SortUsingDeclarationsOptions> { 641bdd1243dSDimitry Andric static void enumeration(IO &IO, 642bdd1243dSDimitry Andric FormatStyle::SortUsingDeclarationsOptions &Value) { 643bdd1243dSDimitry Andric IO.enumCase(Value, "Never", FormatStyle::SUD_Never); 644bdd1243dSDimitry Andric IO.enumCase(Value, "Lexicographic", FormatStyle::SUD_Lexicographic); 645bdd1243dSDimitry Andric IO.enumCase(Value, "LexicographicNumeric", 646bdd1243dSDimitry Andric FormatStyle::SUD_LexicographicNumeric); 647fe6060f1SDimitry Andric 648fe6060f1SDimitry Andric // For backward compatibility. 649bdd1243dSDimitry Andric IO.enumCase(Value, "false", FormatStyle::SUD_Never); 650bdd1243dSDimitry Andric IO.enumCase(Value, "true", FormatStyle::SUD_LexicographicNumeric); 651fe6060f1SDimitry Andric } 652fe6060f1SDimitry Andric }; 653fe6060f1SDimitry Andric 654bdd1243dSDimitry Andric template <> 655bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::SpaceAroundPointerQualifiersStyle> { 656bdd1243dSDimitry Andric static void 657bdd1243dSDimitry Andric enumeration(IO &IO, FormatStyle::SpaceAroundPointerQualifiersStyle &Value) { 658bdd1243dSDimitry Andric IO.enumCase(Value, "Default", FormatStyle::SAPQ_Default); 659bdd1243dSDimitry Andric IO.enumCase(Value, "Before", FormatStyle::SAPQ_Before); 660bdd1243dSDimitry Andric IO.enumCase(Value, "After", FormatStyle::SAPQ_After); 661bdd1243dSDimitry Andric IO.enumCase(Value, "Both", FormatStyle::SAPQ_Both); 6620b57cec5SDimitry Andric } 6630b57cec5SDimitry Andric }; 6640b57cec5SDimitry Andric 665349cc55cSDimitry Andric template <> struct MappingTraits<FormatStyle::SpaceBeforeParensCustom> { 666349cc55cSDimitry Andric static void mapping(IO &IO, FormatStyle::SpaceBeforeParensCustom &Spacing) { 667349cc55cSDimitry Andric IO.mapOptional("AfterControlStatements", Spacing.AfterControlStatements); 668349cc55cSDimitry Andric IO.mapOptional("AfterForeachMacros", Spacing.AfterForeachMacros); 669349cc55cSDimitry Andric IO.mapOptional("AfterFunctionDefinitionName", 670349cc55cSDimitry Andric Spacing.AfterFunctionDefinitionName); 671349cc55cSDimitry Andric IO.mapOptional("AfterFunctionDeclarationName", 672349cc55cSDimitry Andric Spacing.AfterFunctionDeclarationName); 673349cc55cSDimitry Andric IO.mapOptional("AfterIfMacros", Spacing.AfterIfMacros); 67404eeddc0SDimitry Andric IO.mapOptional("AfterOverloadedOperator", Spacing.AfterOverloadedOperator); 6755f757f3fSDimitry Andric IO.mapOptional("AfterPlacementOperator", Spacing.AfterPlacementOperator); 67681ad6265SDimitry Andric IO.mapOptional("AfterRequiresInClause", Spacing.AfterRequiresInClause); 67781ad6265SDimitry Andric IO.mapOptional("AfterRequiresInExpression", 67881ad6265SDimitry Andric Spacing.AfterRequiresInExpression); 679349cc55cSDimitry Andric IO.mapOptional("BeforeNonEmptyParentheses", 680349cc55cSDimitry Andric Spacing.BeforeNonEmptyParentheses); 681349cc55cSDimitry Andric } 682349cc55cSDimitry Andric }; 683349cc55cSDimitry Andric 684bdd1243dSDimitry Andric template <> 685bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensStyle> { 686bdd1243dSDimitry Andric static void enumeration(IO &IO, FormatStyle::SpaceBeforeParensStyle &Value) { 687bdd1243dSDimitry Andric IO.enumCase(Value, "Never", FormatStyle::SBPO_Never); 688bdd1243dSDimitry Andric IO.enumCase(Value, "ControlStatements", 689bdd1243dSDimitry Andric FormatStyle::SBPO_ControlStatements); 690bdd1243dSDimitry Andric IO.enumCase(Value, "ControlStatementsExceptControlMacros", 691bdd1243dSDimitry Andric FormatStyle::SBPO_ControlStatementsExceptControlMacros); 692bdd1243dSDimitry Andric IO.enumCase(Value, "NonEmptyParentheses", 693bdd1243dSDimitry Andric FormatStyle::SBPO_NonEmptyParentheses); 694bdd1243dSDimitry Andric IO.enumCase(Value, "Always", FormatStyle::SBPO_Always); 695bdd1243dSDimitry Andric IO.enumCase(Value, "Custom", FormatStyle::SBPO_Custom); 696bdd1243dSDimitry Andric 697bdd1243dSDimitry Andric // For backward compatibility. 698bdd1243dSDimitry Andric IO.enumCase(Value, "false", FormatStyle::SBPO_Never); 699bdd1243dSDimitry Andric IO.enumCase(Value, "true", FormatStyle::SBPO_ControlStatements); 700bdd1243dSDimitry Andric IO.enumCase(Value, "ControlStatementsExceptForEachMacros", 701bdd1243dSDimitry Andric FormatStyle::SBPO_ControlStatementsExceptControlMacros); 702bdd1243dSDimitry Andric } 703bdd1243dSDimitry Andric }; 704bdd1243dSDimitry Andric 705bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::SpacesInAnglesStyle> { 706bdd1243dSDimitry Andric static void enumeration(IO &IO, FormatStyle::SpacesInAnglesStyle &Value) { 707bdd1243dSDimitry Andric IO.enumCase(Value, "Never", FormatStyle::SIAS_Never); 708bdd1243dSDimitry Andric IO.enumCase(Value, "Always", FormatStyle::SIAS_Always); 709bdd1243dSDimitry Andric IO.enumCase(Value, "Leave", FormatStyle::SIAS_Leave); 710bdd1243dSDimitry Andric 711bdd1243dSDimitry Andric // For backward compatibility. 712bdd1243dSDimitry Andric IO.enumCase(Value, "false", FormatStyle::SIAS_Never); 713bdd1243dSDimitry Andric IO.enumCase(Value, "true", FormatStyle::SIAS_Always); 7140b57cec5SDimitry Andric } 7150b57cec5SDimitry Andric }; 7160b57cec5SDimitry Andric 717fe6060f1SDimitry Andric template <> struct MappingTraits<FormatStyle::SpacesInLineComment> { 718fe6060f1SDimitry Andric static void mapping(IO &IO, FormatStyle::SpacesInLineComment &Space) { 719fe6060f1SDimitry Andric // Transform the maximum to signed, to parse "-1" correctly 720fe6060f1SDimitry Andric int signedMaximum = static_cast<int>(Space.Maximum); 721fe6060f1SDimitry Andric IO.mapOptional("Minimum", Space.Minimum); 722fe6060f1SDimitry Andric IO.mapOptional("Maximum", signedMaximum); 723fe6060f1SDimitry Andric Space.Maximum = static_cast<unsigned>(signedMaximum); 724fe6060f1SDimitry Andric 72581ad6265SDimitry Andric if (Space.Maximum != -1u) 726fe6060f1SDimitry Andric Space.Minimum = std::min(Space.Minimum, Space.Maximum); 727fe6060f1SDimitry Andric } 728fe6060f1SDimitry Andric }; 729fe6060f1SDimitry Andric 73006c3fb27SDimitry Andric template <> struct MappingTraits<FormatStyle::SpacesInParensCustom> { 73106c3fb27SDimitry Andric static void mapping(IO &IO, FormatStyle::SpacesInParensCustom &Spaces) { 732*0fca6ea1SDimitry Andric IO.mapOptional("ExceptDoubleParentheses", Spaces.ExceptDoubleParentheses); 73306c3fb27SDimitry Andric IO.mapOptional("InCStyleCasts", Spaces.InCStyleCasts); 73406c3fb27SDimitry Andric IO.mapOptional("InConditionalStatements", Spaces.InConditionalStatements); 73506c3fb27SDimitry Andric IO.mapOptional("InEmptyParentheses", Spaces.InEmptyParentheses); 73606c3fb27SDimitry Andric IO.mapOptional("Other", Spaces.Other); 73706c3fb27SDimitry Andric } 73806c3fb27SDimitry Andric }; 73906c3fb27SDimitry Andric 74006c3fb27SDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::SpacesInParensStyle> { 74106c3fb27SDimitry Andric static void enumeration(IO &IO, FormatStyle::SpacesInParensStyle &Value) { 74206c3fb27SDimitry Andric IO.enumCase(Value, "Never", FormatStyle::SIPO_Never); 74306c3fb27SDimitry Andric IO.enumCase(Value, "Custom", FormatStyle::SIPO_Custom); 74406c3fb27SDimitry Andric } 74506c3fb27SDimitry Andric }; 74606c3fb27SDimitry Andric 747bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::TrailingCommaStyle> { 748bdd1243dSDimitry Andric static void enumeration(IO &IO, FormatStyle::TrailingCommaStyle &Value) { 749bdd1243dSDimitry Andric IO.enumCase(Value, "None", FormatStyle::TCS_None); 750bdd1243dSDimitry Andric IO.enumCase(Value, "Wrapped", FormatStyle::TCS_Wrapped); 751bdd1243dSDimitry Andric } 752bdd1243dSDimitry Andric }; 753bdd1243dSDimitry Andric 754bdd1243dSDimitry Andric template <> 755bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::TrailingCommentsAlignmentKinds> { 756bdd1243dSDimitry Andric static void enumeration(IO &IO, 757bdd1243dSDimitry Andric FormatStyle::TrailingCommentsAlignmentKinds &Value) { 758bdd1243dSDimitry Andric IO.enumCase(Value, "Leave", FormatStyle::TCAS_Leave); 759bdd1243dSDimitry Andric IO.enumCase(Value, "Always", FormatStyle::TCAS_Always); 760bdd1243dSDimitry Andric IO.enumCase(Value, "Never", FormatStyle::TCAS_Never); 761bdd1243dSDimitry Andric } 762bdd1243dSDimitry Andric }; 763bdd1243dSDimitry Andric 764bdd1243dSDimitry Andric template <> struct MappingTraits<FormatStyle::TrailingCommentsAlignmentStyle> { 765bdd1243dSDimitry Andric static void enumInput(IO &IO, 766bdd1243dSDimitry Andric FormatStyle::TrailingCommentsAlignmentStyle &Value) { 767bdd1243dSDimitry Andric IO.enumCase(Value, "Leave", 768bdd1243dSDimitry Andric FormatStyle::TrailingCommentsAlignmentStyle( 7699e7101a8SDimitry Andric {FormatStyle::TCAS_Leave, 0})); 770bdd1243dSDimitry Andric 771bdd1243dSDimitry Andric IO.enumCase(Value, "Always", 772bdd1243dSDimitry Andric FormatStyle::TrailingCommentsAlignmentStyle( 7739e7101a8SDimitry Andric {FormatStyle::TCAS_Always, 0})); 774bdd1243dSDimitry Andric 775bdd1243dSDimitry Andric IO.enumCase(Value, "Never", 776bdd1243dSDimitry Andric FormatStyle::TrailingCommentsAlignmentStyle( 7779e7101a8SDimitry Andric {FormatStyle::TCAS_Never, 0})); 778bdd1243dSDimitry Andric 779bdd1243dSDimitry Andric // For backwards compatibility 780bdd1243dSDimitry Andric IO.enumCase(Value, "true", 781bdd1243dSDimitry Andric FormatStyle::TrailingCommentsAlignmentStyle( 7829e7101a8SDimitry Andric {FormatStyle::TCAS_Always, 0})); 783bdd1243dSDimitry Andric IO.enumCase(Value, "false", 784bdd1243dSDimitry Andric FormatStyle::TrailingCommentsAlignmentStyle( 7859e7101a8SDimitry Andric {FormatStyle::TCAS_Never, 0})); 786bdd1243dSDimitry Andric } 787bdd1243dSDimitry Andric 788bdd1243dSDimitry Andric static void mapping(IO &IO, 789bdd1243dSDimitry Andric FormatStyle::TrailingCommentsAlignmentStyle &Value) { 790bdd1243dSDimitry Andric IO.mapOptional("Kind", Value.Kind); 791bdd1243dSDimitry Andric IO.mapOptional("OverEmptyLines", Value.OverEmptyLines); 792bdd1243dSDimitry Andric } 793bdd1243dSDimitry Andric }; 794bdd1243dSDimitry Andric 795bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::UseTabStyle> { 796bdd1243dSDimitry Andric static void enumeration(IO &IO, FormatStyle::UseTabStyle &Value) { 797bdd1243dSDimitry Andric IO.enumCase(Value, "Never", FormatStyle::UT_Never); 798bdd1243dSDimitry Andric IO.enumCase(Value, "false", FormatStyle::UT_Never); 799bdd1243dSDimitry Andric IO.enumCase(Value, "Always", FormatStyle::UT_Always); 800bdd1243dSDimitry Andric IO.enumCase(Value, "true", FormatStyle::UT_Always); 801bdd1243dSDimitry Andric IO.enumCase(Value, "ForIndentation", FormatStyle::UT_ForIndentation); 802bdd1243dSDimitry Andric IO.enumCase(Value, "ForContinuationAndIndentation", 803bdd1243dSDimitry Andric FormatStyle::UT_ForContinuationAndIndentation); 804bdd1243dSDimitry Andric IO.enumCase(Value, "AlignWithSpaces", FormatStyle::UT_AlignWithSpaces); 805bdd1243dSDimitry Andric } 806bdd1243dSDimitry Andric }; 807bdd1243dSDimitry Andric 808bdd1243dSDimitry Andric template <> struct MappingTraits<FormatStyle> { 809bdd1243dSDimitry Andric static void mapping(IO &IO, FormatStyle &Style) { 810bdd1243dSDimitry Andric // When reading, read the language first, we need it for getPredefinedStyle. 811bdd1243dSDimitry Andric IO.mapOptional("Language", Style.Language); 812bdd1243dSDimitry Andric 813bdd1243dSDimitry Andric StringRef BasedOnStyle; 814bdd1243dSDimitry Andric if (IO.outputting()) { 815bdd1243dSDimitry Andric StringRef Styles[] = {"LLVM", "Google", "Chromium", "Mozilla", 8165f757f3fSDimitry Andric "WebKit", "GNU", "Microsoft", "clang-format"}; 817bdd1243dSDimitry Andric for (StringRef StyleName : Styles) { 818bdd1243dSDimitry Andric FormatStyle PredefinedStyle; 819bdd1243dSDimitry Andric if (getPredefinedStyle(StyleName, Style.Language, &PredefinedStyle) && 820bdd1243dSDimitry Andric Style == PredefinedStyle) { 821bdd1243dSDimitry Andric BasedOnStyle = StyleName; 822bdd1243dSDimitry Andric break; 823bdd1243dSDimitry Andric } 824bdd1243dSDimitry Andric } 825bdd1243dSDimitry Andric } else { 826bdd1243dSDimitry Andric IO.mapOptional("BasedOnStyle", BasedOnStyle); 827bdd1243dSDimitry Andric if (!BasedOnStyle.empty()) { 828bdd1243dSDimitry Andric FormatStyle::LanguageKind OldLanguage = Style.Language; 829bdd1243dSDimitry Andric FormatStyle::LanguageKind Language = 830bdd1243dSDimitry Andric ((FormatStyle *)IO.getContext())->Language; 831bdd1243dSDimitry Andric if (!getPredefinedStyle(BasedOnStyle, Language, &Style)) { 832bdd1243dSDimitry Andric IO.setError(Twine("Unknown value for BasedOnStyle: ", BasedOnStyle)); 833bdd1243dSDimitry Andric return; 834bdd1243dSDimitry Andric } 835bdd1243dSDimitry Andric Style.Language = OldLanguage; 836bdd1243dSDimitry Andric } 837bdd1243dSDimitry Andric } 838bdd1243dSDimitry Andric 839bdd1243dSDimitry Andric // Initialize some variables used in the parsing. The using logic is at the 840bdd1243dSDimitry Andric // end. 841bdd1243dSDimitry Andric 842bdd1243dSDimitry Andric // For backward compatibility: 843bdd1243dSDimitry Andric // The default value of ConstructorInitializerAllOnOneLineOrOnePerLine was 844bdd1243dSDimitry Andric // false unless BasedOnStyle was Google or Chromium whereas that of 845bdd1243dSDimitry Andric // AllowAllConstructorInitializersOnNextLine was always true, so the 846bdd1243dSDimitry Andric // equivalent default value of PackConstructorInitializers is PCIS_NextLine 847bdd1243dSDimitry Andric // for Google/Chromium or PCIS_BinPack otherwise. If the deprecated options 848bdd1243dSDimitry Andric // had a non-default value while PackConstructorInitializers has a default 849bdd1243dSDimitry Andric // value, set the latter to an equivalent non-default value if needed. 850bdd1243dSDimitry Andric const bool IsGoogleOrChromium = BasedOnStyle.equals_insensitive("google") || 851bdd1243dSDimitry Andric BasedOnStyle.equals_insensitive("chromium"); 852bdd1243dSDimitry Andric bool OnCurrentLine = IsGoogleOrChromium; 853bdd1243dSDimitry Andric bool OnNextLine = true; 854bdd1243dSDimitry Andric 855bdd1243dSDimitry Andric bool BreakBeforeInheritanceComma = false; 856bdd1243dSDimitry Andric bool BreakConstructorInitializersBeforeComma = false; 857bdd1243dSDimitry Andric 858bdd1243dSDimitry Andric bool DeriveLineEnding = true; 859bdd1243dSDimitry Andric bool UseCRLF = false; 860bdd1243dSDimitry Andric 86106c3fb27SDimitry Andric bool SpaceInEmptyParentheses = false; 86206c3fb27SDimitry Andric bool SpacesInConditionalStatement = false; 86306c3fb27SDimitry Andric bool SpacesInCStyleCastParentheses = false; 86406c3fb27SDimitry Andric bool SpacesInParentheses = false; 86506c3fb27SDimitry Andric 866bdd1243dSDimitry Andric // For backward compatibility. 867bdd1243dSDimitry Andric if (!IO.outputting()) { 868bdd1243dSDimitry Andric IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlines); 869bdd1243dSDimitry Andric IO.mapOptional("AllowAllConstructorInitializersOnNextLine", OnNextLine); 870*0fca6ea1SDimitry Andric IO.mapOptional("AlwaysBreakAfterReturnType", Style.BreakAfterReturnType); 871*0fca6ea1SDimitry Andric IO.mapOptional("AlwaysBreakTemplateDeclarations", 872*0fca6ea1SDimitry Andric Style.BreakTemplateDeclarations); 873bdd1243dSDimitry Andric IO.mapOptional("BreakBeforeInheritanceComma", 874bdd1243dSDimitry Andric BreakBeforeInheritanceComma); 875bdd1243dSDimitry Andric IO.mapOptional("BreakConstructorInitializersBeforeComma", 876bdd1243dSDimitry Andric BreakConstructorInitializersBeforeComma); 877bdd1243dSDimitry Andric IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine", 878bdd1243dSDimitry Andric OnCurrentLine); 879bdd1243dSDimitry Andric IO.mapOptional("DeriveLineEnding", DeriveLineEnding); 880bdd1243dSDimitry Andric IO.mapOptional("DerivePointerBinding", Style.DerivePointerAlignment); 881*0fca6ea1SDimitry Andric IO.mapOptional("KeepEmptyLinesAtEOF", Style.KeepEmptyLines.AtEndOfFile); 882*0fca6ea1SDimitry Andric IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks", 883*0fca6ea1SDimitry Andric Style.KeepEmptyLines.AtStartOfBlock); 884bdd1243dSDimitry Andric IO.mapOptional("IndentFunctionDeclarationAfterType", 885bdd1243dSDimitry Andric Style.IndentWrappedFunctionNames); 886bdd1243dSDimitry Andric IO.mapOptional("IndentRequires", Style.IndentRequiresClause); 887bdd1243dSDimitry Andric IO.mapOptional("PointerBindsToType", Style.PointerAlignment); 888bdd1243dSDimitry Andric IO.mapOptional("SpaceAfterControlStatementKeyword", 889bdd1243dSDimitry Andric Style.SpaceBeforeParens); 89006c3fb27SDimitry Andric IO.mapOptional("SpaceInEmptyParentheses", SpaceInEmptyParentheses); 89106c3fb27SDimitry Andric IO.mapOptional("SpacesInConditionalStatement", 89206c3fb27SDimitry Andric SpacesInConditionalStatement); 89306c3fb27SDimitry Andric IO.mapOptional("SpacesInCStyleCastParentheses", 89406c3fb27SDimitry Andric SpacesInCStyleCastParentheses); 89506c3fb27SDimitry Andric IO.mapOptional("SpacesInParentheses", SpacesInParentheses); 896bdd1243dSDimitry Andric IO.mapOptional("UseCRLF", UseCRLF); 897bdd1243dSDimitry Andric } 898bdd1243dSDimitry Andric 899bdd1243dSDimitry Andric IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset); 900bdd1243dSDimitry Andric IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket); 901bdd1243dSDimitry Andric IO.mapOptional("AlignArrayOfStructures", Style.AlignArrayOfStructures); 902bdd1243dSDimitry Andric IO.mapOptional("AlignConsecutiveAssignments", 903bdd1243dSDimitry Andric Style.AlignConsecutiveAssignments); 904bdd1243dSDimitry Andric IO.mapOptional("AlignConsecutiveBitFields", 905bdd1243dSDimitry Andric Style.AlignConsecutiveBitFields); 906bdd1243dSDimitry Andric IO.mapOptional("AlignConsecutiveDeclarations", 907bdd1243dSDimitry Andric Style.AlignConsecutiveDeclarations); 908bdd1243dSDimitry Andric IO.mapOptional("AlignConsecutiveMacros", Style.AlignConsecutiveMacros); 90906c3fb27SDimitry Andric IO.mapOptional("AlignConsecutiveShortCaseStatements", 91006c3fb27SDimitry Andric Style.AlignConsecutiveShortCaseStatements); 911*0fca6ea1SDimitry Andric IO.mapOptional("AlignConsecutiveTableGenBreakingDAGArgColons", 912*0fca6ea1SDimitry Andric Style.AlignConsecutiveTableGenBreakingDAGArgColons); 913*0fca6ea1SDimitry Andric IO.mapOptional("AlignConsecutiveTableGenCondOperatorColons", 914*0fca6ea1SDimitry Andric Style.AlignConsecutiveTableGenCondOperatorColons); 915*0fca6ea1SDimitry Andric IO.mapOptional("AlignConsecutiveTableGenDefinitionColons", 916*0fca6ea1SDimitry Andric Style.AlignConsecutiveTableGenDefinitionColons); 917bdd1243dSDimitry Andric IO.mapOptional("AlignEscapedNewlines", Style.AlignEscapedNewlines); 918bdd1243dSDimitry Andric IO.mapOptional("AlignOperands", Style.AlignOperands); 919bdd1243dSDimitry Andric IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments); 920bdd1243dSDimitry Andric IO.mapOptional("AllowAllArgumentsOnNextLine", 921bdd1243dSDimitry Andric Style.AllowAllArgumentsOnNextLine); 922bdd1243dSDimitry Andric IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine", 923bdd1243dSDimitry Andric Style.AllowAllParametersOfDeclarationOnNextLine); 9245f757f3fSDimitry Andric IO.mapOptional("AllowBreakBeforeNoexceptSpecifier", 9255f757f3fSDimitry Andric Style.AllowBreakBeforeNoexceptSpecifier); 926bdd1243dSDimitry Andric IO.mapOptional("AllowShortBlocksOnASingleLine", 927bdd1243dSDimitry Andric Style.AllowShortBlocksOnASingleLine); 928*0fca6ea1SDimitry Andric IO.mapOptional("AllowShortCaseExpressionOnASingleLine", 929*0fca6ea1SDimitry Andric Style.AllowShortCaseExpressionOnASingleLine); 930bdd1243dSDimitry Andric IO.mapOptional("AllowShortCaseLabelsOnASingleLine", 931bdd1243dSDimitry Andric Style.AllowShortCaseLabelsOnASingleLine); 9325f757f3fSDimitry Andric IO.mapOptional("AllowShortCompoundRequirementOnASingleLine", 9335f757f3fSDimitry Andric Style.AllowShortCompoundRequirementOnASingleLine); 934bdd1243dSDimitry Andric IO.mapOptional("AllowShortEnumsOnASingleLine", 935bdd1243dSDimitry Andric Style.AllowShortEnumsOnASingleLine); 936bdd1243dSDimitry Andric IO.mapOptional("AllowShortFunctionsOnASingleLine", 937bdd1243dSDimitry Andric Style.AllowShortFunctionsOnASingleLine); 938bdd1243dSDimitry Andric IO.mapOptional("AllowShortIfStatementsOnASingleLine", 939bdd1243dSDimitry Andric Style.AllowShortIfStatementsOnASingleLine); 940bdd1243dSDimitry Andric IO.mapOptional("AllowShortLambdasOnASingleLine", 941bdd1243dSDimitry Andric Style.AllowShortLambdasOnASingleLine); 942bdd1243dSDimitry Andric IO.mapOptional("AllowShortLoopsOnASingleLine", 943bdd1243dSDimitry Andric Style.AllowShortLoopsOnASingleLine); 944bdd1243dSDimitry Andric IO.mapOptional("AlwaysBreakAfterDefinitionReturnType", 945bdd1243dSDimitry Andric Style.AlwaysBreakAfterDefinitionReturnType); 946bdd1243dSDimitry Andric IO.mapOptional("AlwaysBreakBeforeMultilineStrings", 947bdd1243dSDimitry Andric Style.AlwaysBreakBeforeMultilineStrings); 948bdd1243dSDimitry Andric IO.mapOptional("AttributeMacros", Style.AttributeMacros); 949bdd1243dSDimitry Andric IO.mapOptional("BinPackArguments", Style.BinPackArguments); 950bdd1243dSDimitry Andric IO.mapOptional("BinPackParameters", Style.BinPackParameters); 951bdd1243dSDimitry Andric IO.mapOptional("BitFieldColonSpacing", Style.BitFieldColonSpacing); 95206c3fb27SDimitry Andric IO.mapOptional("BracedInitializerIndentWidth", 95306c3fb27SDimitry Andric Style.BracedInitializerIndentWidth); 954bdd1243dSDimitry Andric IO.mapOptional("BraceWrapping", Style.BraceWrapping); 9555f757f3fSDimitry Andric IO.mapOptional("BreakAdjacentStringLiterals", 9565f757f3fSDimitry Andric Style.BreakAdjacentStringLiterals); 957bdd1243dSDimitry Andric IO.mapOptional("BreakAfterAttributes", Style.BreakAfterAttributes); 958bdd1243dSDimitry Andric IO.mapOptional("BreakAfterJavaFieldAnnotations", 959bdd1243dSDimitry Andric Style.BreakAfterJavaFieldAnnotations); 960*0fca6ea1SDimitry Andric IO.mapOptional("BreakAfterReturnType", Style.BreakAfterReturnType); 961bdd1243dSDimitry Andric IO.mapOptional("BreakArrays", Style.BreakArrays); 962bdd1243dSDimitry Andric IO.mapOptional("BreakBeforeBinaryOperators", 963bdd1243dSDimitry Andric Style.BreakBeforeBinaryOperators); 964bdd1243dSDimitry Andric IO.mapOptional("BreakBeforeConceptDeclarations", 965bdd1243dSDimitry Andric Style.BreakBeforeConceptDeclarations); 966bdd1243dSDimitry Andric IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces); 967bdd1243dSDimitry Andric IO.mapOptional("BreakBeforeInlineASMColon", 968bdd1243dSDimitry Andric Style.BreakBeforeInlineASMColon); 969bdd1243dSDimitry Andric IO.mapOptional("BreakBeforeTernaryOperators", 970bdd1243dSDimitry Andric Style.BreakBeforeTernaryOperators); 971bdd1243dSDimitry Andric IO.mapOptional("BreakConstructorInitializers", 972bdd1243dSDimitry Andric Style.BreakConstructorInitializers); 973*0fca6ea1SDimitry Andric IO.mapOptional("BreakFunctionDefinitionParameters", 974*0fca6ea1SDimitry Andric Style.BreakFunctionDefinitionParameters); 975bdd1243dSDimitry Andric IO.mapOptional("BreakInheritanceList", Style.BreakInheritanceList); 976bdd1243dSDimitry Andric IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals); 977*0fca6ea1SDimitry Andric IO.mapOptional("BreakTemplateDeclarations", 978*0fca6ea1SDimitry Andric Style.BreakTemplateDeclarations); 979bdd1243dSDimitry Andric IO.mapOptional("ColumnLimit", Style.ColumnLimit); 980bdd1243dSDimitry Andric IO.mapOptional("CommentPragmas", Style.CommentPragmas); 981bdd1243dSDimitry Andric IO.mapOptional("CompactNamespaces", Style.CompactNamespaces); 982bdd1243dSDimitry Andric IO.mapOptional("ConstructorInitializerIndentWidth", 983bdd1243dSDimitry Andric Style.ConstructorInitializerIndentWidth); 984bdd1243dSDimitry Andric IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth); 985bdd1243dSDimitry Andric IO.mapOptional("Cpp11BracedListStyle", Style.Cpp11BracedListStyle); 986bdd1243dSDimitry Andric IO.mapOptional("DerivePointerAlignment", Style.DerivePointerAlignment); 987bdd1243dSDimitry Andric IO.mapOptional("DisableFormat", Style.DisableFormat); 988bdd1243dSDimitry Andric IO.mapOptional("EmptyLineAfterAccessModifier", 989bdd1243dSDimitry Andric Style.EmptyLineAfterAccessModifier); 990bdd1243dSDimitry Andric IO.mapOptional("EmptyLineBeforeAccessModifier", 991bdd1243dSDimitry Andric Style.EmptyLineBeforeAccessModifier); 992bdd1243dSDimitry Andric IO.mapOptional("ExperimentalAutoDetectBinPacking", 993bdd1243dSDimitry Andric Style.ExperimentalAutoDetectBinPacking); 994bdd1243dSDimitry Andric IO.mapOptional("FixNamespaceComments", Style.FixNamespaceComments); 995bdd1243dSDimitry Andric IO.mapOptional("ForEachMacros", Style.ForEachMacros); 996bdd1243dSDimitry Andric IO.mapOptional("IfMacros", Style.IfMacros); 997bdd1243dSDimitry Andric IO.mapOptional("IncludeBlocks", Style.IncludeStyle.IncludeBlocks); 998bdd1243dSDimitry Andric IO.mapOptional("IncludeCategories", Style.IncludeStyle.IncludeCategories); 999bdd1243dSDimitry Andric IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex); 1000bdd1243dSDimitry Andric IO.mapOptional("IncludeIsMainSourceRegex", 1001bdd1243dSDimitry Andric Style.IncludeStyle.IncludeIsMainSourceRegex); 1002bdd1243dSDimitry Andric IO.mapOptional("IndentAccessModifiers", Style.IndentAccessModifiers); 1003bdd1243dSDimitry Andric IO.mapOptional("IndentCaseBlocks", Style.IndentCaseBlocks); 1004bdd1243dSDimitry Andric IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels); 1005bdd1243dSDimitry Andric IO.mapOptional("IndentExternBlock", Style.IndentExternBlock); 1006bdd1243dSDimitry Andric IO.mapOptional("IndentGotoLabels", Style.IndentGotoLabels); 1007bdd1243dSDimitry Andric IO.mapOptional("IndentPPDirectives", Style.IndentPPDirectives); 1008bdd1243dSDimitry Andric IO.mapOptional("IndentRequiresClause", Style.IndentRequiresClause); 1009bdd1243dSDimitry Andric IO.mapOptional("IndentWidth", Style.IndentWidth); 1010bdd1243dSDimitry Andric IO.mapOptional("IndentWrappedFunctionNames", 1011bdd1243dSDimitry Andric Style.IndentWrappedFunctionNames); 1012bdd1243dSDimitry Andric IO.mapOptional("InsertBraces", Style.InsertBraces); 1013bdd1243dSDimitry Andric IO.mapOptional("InsertNewlineAtEOF", Style.InsertNewlineAtEOF); 1014bdd1243dSDimitry Andric IO.mapOptional("InsertTrailingCommas", Style.InsertTrailingCommas); 1015bdd1243dSDimitry Andric IO.mapOptional("IntegerLiteralSeparator", Style.IntegerLiteralSeparator); 1016bdd1243dSDimitry Andric IO.mapOptional("JavaImportGroups", Style.JavaImportGroups); 1017bdd1243dSDimitry Andric IO.mapOptional("JavaScriptQuotes", Style.JavaScriptQuotes); 1018bdd1243dSDimitry Andric IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports); 1019*0fca6ea1SDimitry Andric IO.mapOptional("KeepEmptyLines", Style.KeepEmptyLines); 1020bdd1243dSDimitry Andric IO.mapOptional("LambdaBodyIndentation", Style.LambdaBodyIndentation); 1021bdd1243dSDimitry Andric IO.mapOptional("LineEnding", Style.LineEnding); 1022bdd1243dSDimitry Andric IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin); 1023bdd1243dSDimitry Andric IO.mapOptional("MacroBlockEnd", Style.MacroBlockEnd); 10245f757f3fSDimitry Andric IO.mapOptional("Macros", Style.Macros); 1025*0fca6ea1SDimitry Andric IO.mapOptional("MainIncludeChar", Style.IncludeStyle.MainIncludeChar); 1026bdd1243dSDimitry Andric IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep); 1027bdd1243dSDimitry Andric IO.mapOptional("NamespaceIndentation", Style.NamespaceIndentation); 1028bdd1243dSDimitry Andric IO.mapOptional("NamespaceMacros", Style.NamespaceMacros); 1029bdd1243dSDimitry Andric IO.mapOptional("ObjCBinPackProtocolList", Style.ObjCBinPackProtocolList); 1030bdd1243dSDimitry Andric IO.mapOptional("ObjCBlockIndentWidth", Style.ObjCBlockIndentWidth); 1031bdd1243dSDimitry Andric IO.mapOptional("ObjCBreakBeforeNestedBlockParam", 1032bdd1243dSDimitry Andric Style.ObjCBreakBeforeNestedBlockParam); 10335f757f3fSDimitry Andric IO.mapOptional("ObjCPropertyAttributeOrder", 10345f757f3fSDimitry Andric Style.ObjCPropertyAttributeOrder); 1035bdd1243dSDimitry Andric IO.mapOptional("ObjCSpaceAfterProperty", Style.ObjCSpaceAfterProperty); 1036bdd1243dSDimitry Andric IO.mapOptional("ObjCSpaceBeforeProtocolList", 1037bdd1243dSDimitry Andric Style.ObjCSpaceBeforeProtocolList); 1038bdd1243dSDimitry Andric IO.mapOptional("PackConstructorInitializers", 1039bdd1243dSDimitry Andric Style.PackConstructorInitializers); 1040bdd1243dSDimitry Andric IO.mapOptional("PenaltyBreakAssignment", Style.PenaltyBreakAssignment); 1041bdd1243dSDimitry Andric IO.mapOptional("PenaltyBreakBeforeFirstCallParameter", 1042bdd1243dSDimitry Andric Style.PenaltyBreakBeforeFirstCallParameter); 1043bdd1243dSDimitry Andric IO.mapOptional("PenaltyBreakComment", Style.PenaltyBreakComment); 1044bdd1243dSDimitry Andric IO.mapOptional("PenaltyBreakFirstLessLess", 1045bdd1243dSDimitry Andric Style.PenaltyBreakFirstLessLess); 1046bdd1243dSDimitry Andric IO.mapOptional("PenaltyBreakOpenParenthesis", 1047bdd1243dSDimitry Andric Style.PenaltyBreakOpenParenthesis); 10487a6dacacSDimitry Andric IO.mapOptional("PenaltyBreakScopeResolution", 10497a6dacacSDimitry Andric Style.PenaltyBreakScopeResolution); 1050bdd1243dSDimitry Andric IO.mapOptional("PenaltyBreakString", Style.PenaltyBreakString); 1051bdd1243dSDimitry Andric IO.mapOptional("PenaltyBreakTemplateDeclaration", 1052bdd1243dSDimitry Andric Style.PenaltyBreakTemplateDeclaration); 1053bdd1243dSDimitry Andric IO.mapOptional("PenaltyExcessCharacter", Style.PenaltyExcessCharacter); 1054bdd1243dSDimitry Andric IO.mapOptional("PenaltyIndentedWhitespace", 1055bdd1243dSDimitry Andric Style.PenaltyIndentedWhitespace); 1056bdd1243dSDimitry Andric IO.mapOptional("PenaltyReturnTypeOnItsOwnLine", 1057bdd1243dSDimitry Andric Style.PenaltyReturnTypeOnItsOwnLine); 1058bdd1243dSDimitry Andric IO.mapOptional("PointerAlignment", Style.PointerAlignment); 1059bdd1243dSDimitry Andric IO.mapOptional("PPIndentWidth", Style.PPIndentWidth); 1060bdd1243dSDimitry Andric IO.mapOptional("QualifierAlignment", Style.QualifierAlignment); 1061bdd1243dSDimitry Andric // Default Order for Left/Right based Qualifier alignment. 1062bdd1243dSDimitry Andric if (Style.QualifierAlignment == FormatStyle::QAS_Right) 1063bdd1243dSDimitry Andric Style.QualifierOrder = {"type", "const", "volatile"}; 1064bdd1243dSDimitry Andric else if (Style.QualifierAlignment == FormatStyle::QAS_Left) 1065bdd1243dSDimitry Andric Style.QualifierOrder = {"const", "volatile", "type"}; 1066bdd1243dSDimitry Andric else if (Style.QualifierAlignment == FormatStyle::QAS_Custom) 1067bdd1243dSDimitry Andric IO.mapOptional("QualifierOrder", Style.QualifierOrder); 1068bdd1243dSDimitry Andric IO.mapOptional("RawStringFormats", Style.RawStringFormats); 1069bdd1243dSDimitry Andric IO.mapOptional("ReferenceAlignment", Style.ReferenceAlignment); 1070bdd1243dSDimitry Andric IO.mapOptional("ReflowComments", Style.ReflowComments); 1071bdd1243dSDimitry Andric IO.mapOptional("RemoveBracesLLVM", Style.RemoveBracesLLVM); 107206c3fb27SDimitry Andric IO.mapOptional("RemoveParentheses", Style.RemoveParentheses); 1073bdd1243dSDimitry Andric IO.mapOptional("RemoveSemicolon", Style.RemoveSemicolon); 1074bdd1243dSDimitry Andric IO.mapOptional("RequiresClausePosition", Style.RequiresClausePosition); 1075bdd1243dSDimitry Andric IO.mapOptional("RequiresExpressionIndentation", 1076bdd1243dSDimitry Andric Style.RequiresExpressionIndentation); 1077bdd1243dSDimitry Andric IO.mapOptional("SeparateDefinitionBlocks", Style.SeparateDefinitionBlocks); 1078bdd1243dSDimitry Andric IO.mapOptional("ShortNamespaceLines", Style.ShortNamespaceLines); 10797a6dacacSDimitry Andric IO.mapOptional("SkipMacroDefinitionBody", Style.SkipMacroDefinitionBody); 1080bdd1243dSDimitry Andric IO.mapOptional("SortIncludes", Style.SortIncludes); 1081bdd1243dSDimitry Andric IO.mapOptional("SortJavaStaticImport", Style.SortJavaStaticImport); 1082bdd1243dSDimitry Andric IO.mapOptional("SortUsingDeclarations", Style.SortUsingDeclarations); 1083bdd1243dSDimitry Andric IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast); 1084bdd1243dSDimitry Andric IO.mapOptional("SpaceAfterLogicalNot", Style.SpaceAfterLogicalNot); 1085bdd1243dSDimitry Andric IO.mapOptional("SpaceAfterTemplateKeyword", 1086bdd1243dSDimitry Andric Style.SpaceAfterTemplateKeyword); 1087bdd1243dSDimitry Andric IO.mapOptional("SpaceAroundPointerQualifiers", 1088bdd1243dSDimitry Andric Style.SpaceAroundPointerQualifiers); 1089bdd1243dSDimitry Andric IO.mapOptional("SpaceBeforeAssignmentOperators", 1090bdd1243dSDimitry Andric Style.SpaceBeforeAssignmentOperators); 1091bdd1243dSDimitry Andric IO.mapOptional("SpaceBeforeCaseColon", Style.SpaceBeforeCaseColon); 1092bdd1243dSDimitry Andric IO.mapOptional("SpaceBeforeCpp11BracedList", 1093bdd1243dSDimitry Andric Style.SpaceBeforeCpp11BracedList); 1094bdd1243dSDimitry Andric IO.mapOptional("SpaceBeforeCtorInitializerColon", 1095bdd1243dSDimitry Andric Style.SpaceBeforeCtorInitializerColon); 1096bdd1243dSDimitry Andric IO.mapOptional("SpaceBeforeInheritanceColon", 1097bdd1243dSDimitry Andric Style.SpaceBeforeInheritanceColon); 109806c3fb27SDimitry Andric IO.mapOptional("SpaceBeforeJsonColon", Style.SpaceBeforeJsonColon); 1099bdd1243dSDimitry Andric IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens); 1100bdd1243dSDimitry Andric IO.mapOptional("SpaceBeforeParensOptions", Style.SpaceBeforeParensOptions); 1101bdd1243dSDimitry Andric IO.mapOptional("SpaceBeforeRangeBasedForLoopColon", 1102bdd1243dSDimitry Andric Style.SpaceBeforeRangeBasedForLoopColon); 1103bdd1243dSDimitry Andric IO.mapOptional("SpaceBeforeSquareBrackets", 1104bdd1243dSDimitry Andric Style.SpaceBeforeSquareBrackets); 1105bdd1243dSDimitry Andric IO.mapOptional("SpaceInEmptyBlock", Style.SpaceInEmptyBlock); 1106bdd1243dSDimitry Andric IO.mapOptional("SpacesBeforeTrailingComments", 1107bdd1243dSDimitry Andric Style.SpacesBeforeTrailingComments); 1108bdd1243dSDimitry Andric IO.mapOptional("SpacesInAngles", Style.SpacesInAngles); 1109bdd1243dSDimitry Andric IO.mapOptional("SpacesInContainerLiterals", 1110bdd1243dSDimitry Andric Style.SpacesInContainerLiterals); 1111bdd1243dSDimitry Andric IO.mapOptional("SpacesInLineCommentPrefix", 1112bdd1243dSDimitry Andric Style.SpacesInLineCommentPrefix); 111306c3fb27SDimitry Andric IO.mapOptional("SpacesInParens", Style.SpacesInParens); 111406c3fb27SDimitry Andric IO.mapOptional("SpacesInParensOptions", Style.SpacesInParensOptions); 1115bdd1243dSDimitry Andric IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets); 1116bdd1243dSDimitry Andric IO.mapOptional("Standard", Style.Standard); 1117bdd1243dSDimitry Andric IO.mapOptional("StatementAttributeLikeMacros", 1118bdd1243dSDimitry Andric Style.StatementAttributeLikeMacros); 1119bdd1243dSDimitry Andric IO.mapOptional("StatementMacros", Style.StatementMacros); 1120*0fca6ea1SDimitry Andric IO.mapOptional("TableGenBreakingDAGArgOperators", 1121*0fca6ea1SDimitry Andric Style.TableGenBreakingDAGArgOperators); 1122*0fca6ea1SDimitry Andric IO.mapOptional("TableGenBreakInsideDAGArg", 1123*0fca6ea1SDimitry Andric Style.TableGenBreakInsideDAGArg); 1124bdd1243dSDimitry Andric IO.mapOptional("TabWidth", Style.TabWidth); 112506c3fb27SDimitry Andric IO.mapOptional("TypeNames", Style.TypeNames); 1126bdd1243dSDimitry Andric IO.mapOptional("TypenameMacros", Style.TypenameMacros); 1127bdd1243dSDimitry Andric IO.mapOptional("UseTab", Style.UseTab); 112806c3fb27SDimitry Andric IO.mapOptional("VerilogBreakBetweenInstancePorts", 112906c3fb27SDimitry Andric Style.VerilogBreakBetweenInstancePorts); 1130bdd1243dSDimitry Andric IO.mapOptional("WhitespaceSensitiveMacros", 1131bdd1243dSDimitry Andric Style.WhitespaceSensitiveMacros); 1132bdd1243dSDimitry Andric 1133bdd1243dSDimitry Andric // If AlwaysBreakAfterDefinitionReturnType was specified but 1134*0fca6ea1SDimitry Andric // BreakAfterReturnType was not, initialize the latter from the former for 1135*0fca6ea1SDimitry Andric // backwards compatibility. 1136bdd1243dSDimitry Andric if (Style.AlwaysBreakAfterDefinitionReturnType != FormatStyle::DRTBS_None && 1137*0fca6ea1SDimitry Andric Style.BreakAfterReturnType == FormatStyle::RTBS_None) { 1138bdd1243dSDimitry Andric if (Style.AlwaysBreakAfterDefinitionReturnType == 1139bdd1243dSDimitry Andric FormatStyle::DRTBS_All) { 1140*0fca6ea1SDimitry Andric Style.BreakAfterReturnType = FormatStyle::RTBS_AllDefinitions; 1141bdd1243dSDimitry Andric } else if (Style.AlwaysBreakAfterDefinitionReturnType == 1142bdd1243dSDimitry Andric FormatStyle::DRTBS_TopLevel) { 1143*0fca6ea1SDimitry Andric Style.BreakAfterReturnType = FormatStyle::RTBS_TopLevelDefinitions; 1144bdd1243dSDimitry Andric } 1145bdd1243dSDimitry Andric } 1146bdd1243dSDimitry Andric 1147bdd1243dSDimitry Andric // If BreakBeforeInheritanceComma was specified but BreakInheritance was 1148bdd1243dSDimitry Andric // not, initialize the latter from the former for backwards compatibility. 1149bdd1243dSDimitry Andric if (BreakBeforeInheritanceComma && 1150bdd1243dSDimitry Andric Style.BreakInheritanceList == FormatStyle::BILS_BeforeColon) { 1151bdd1243dSDimitry Andric Style.BreakInheritanceList = FormatStyle::BILS_BeforeComma; 1152bdd1243dSDimitry Andric } 1153bdd1243dSDimitry Andric 1154bdd1243dSDimitry Andric // If BreakConstructorInitializersBeforeComma was specified but 1155bdd1243dSDimitry Andric // BreakConstructorInitializers was not, initialize the latter from the 1156bdd1243dSDimitry Andric // former for backwards compatibility. 1157bdd1243dSDimitry Andric if (BreakConstructorInitializersBeforeComma && 1158bdd1243dSDimitry Andric Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon) { 1159bdd1243dSDimitry Andric Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma; 1160bdd1243dSDimitry Andric } 1161bdd1243dSDimitry Andric 1162bdd1243dSDimitry Andric if (!IsGoogleOrChromium) { 1163bdd1243dSDimitry Andric if (Style.PackConstructorInitializers == FormatStyle::PCIS_BinPack && 1164bdd1243dSDimitry Andric OnCurrentLine) { 1165bdd1243dSDimitry Andric Style.PackConstructorInitializers = OnNextLine 1166bdd1243dSDimitry Andric ? FormatStyle::PCIS_NextLine 1167bdd1243dSDimitry Andric : FormatStyle::PCIS_CurrentLine; 1168bdd1243dSDimitry Andric } 1169bdd1243dSDimitry Andric } else if (Style.PackConstructorInitializers == 1170bdd1243dSDimitry Andric FormatStyle::PCIS_NextLine) { 1171bdd1243dSDimitry Andric if (!OnCurrentLine) 1172bdd1243dSDimitry Andric Style.PackConstructorInitializers = FormatStyle::PCIS_BinPack; 1173bdd1243dSDimitry Andric else if (!OnNextLine) 1174bdd1243dSDimitry Andric Style.PackConstructorInitializers = FormatStyle::PCIS_CurrentLine; 1175bdd1243dSDimitry Andric } 1176bdd1243dSDimitry Andric 1177bdd1243dSDimitry Andric if (Style.LineEnding == FormatStyle::LE_DeriveLF) { 1178bdd1243dSDimitry Andric if (!DeriveLineEnding) 1179bdd1243dSDimitry Andric Style.LineEnding = UseCRLF ? FormatStyle::LE_CRLF : FormatStyle::LE_LF; 1180bdd1243dSDimitry Andric else if (UseCRLF) 1181bdd1243dSDimitry Andric Style.LineEnding = FormatStyle::LE_DeriveCRLF; 1182bdd1243dSDimitry Andric } 118306c3fb27SDimitry Andric 118406c3fb27SDimitry Andric if (Style.SpacesInParens != FormatStyle::SIPO_Custom && 118506c3fb27SDimitry Andric (SpacesInParentheses || SpaceInEmptyParentheses || 118606c3fb27SDimitry Andric SpacesInConditionalStatement || SpacesInCStyleCastParentheses)) { 118706c3fb27SDimitry Andric if (SpacesInParentheses) { 1188*0fca6ea1SDimitry Andric // For backward compatibility. 1189*0fca6ea1SDimitry Andric Style.SpacesInParensOptions.ExceptDoubleParentheses = false; 119006c3fb27SDimitry Andric Style.SpacesInParensOptions.InConditionalStatements = true; 119106c3fb27SDimitry Andric Style.SpacesInParensOptions.InCStyleCasts = 119206c3fb27SDimitry Andric SpacesInCStyleCastParentheses; 119306c3fb27SDimitry Andric Style.SpacesInParensOptions.InEmptyParentheses = 119406c3fb27SDimitry Andric SpaceInEmptyParentheses; 119506c3fb27SDimitry Andric Style.SpacesInParensOptions.Other = true; 119606c3fb27SDimitry Andric } else { 119706c3fb27SDimitry Andric Style.SpacesInParensOptions = {}; 119806c3fb27SDimitry Andric Style.SpacesInParensOptions.InConditionalStatements = 119906c3fb27SDimitry Andric SpacesInConditionalStatement; 120006c3fb27SDimitry Andric Style.SpacesInParensOptions.InCStyleCasts = 120106c3fb27SDimitry Andric SpacesInCStyleCastParentheses; 120206c3fb27SDimitry Andric Style.SpacesInParensOptions.InEmptyParentheses = 120306c3fb27SDimitry Andric SpaceInEmptyParentheses; 120406c3fb27SDimitry Andric } 120506c3fb27SDimitry Andric Style.SpacesInParens = FormatStyle::SIPO_Custom; 120606c3fb27SDimitry Andric } 1207bdd1243dSDimitry Andric } 1208bdd1243dSDimitry Andric }; 1209bdd1243dSDimitry Andric 12100b57cec5SDimitry Andric // Allows to read vector<FormatStyle> while keeping default values. 12110b57cec5SDimitry Andric // IO.getContext() should contain a pointer to the FormatStyle structure, that 12120b57cec5SDimitry Andric // will be used to get default values for missing keys. 12130b57cec5SDimitry Andric // If the first element has no Language specified, it will be treated as the 12140b57cec5SDimitry Andric // default one for the following elements. 12150b57cec5SDimitry Andric template <> struct DocumentListTraits<std::vector<FormatStyle>> { 12160b57cec5SDimitry Andric static size_t size(IO &IO, std::vector<FormatStyle> &Seq) { 12170b57cec5SDimitry Andric return Seq.size(); 12180b57cec5SDimitry Andric } 12190b57cec5SDimitry Andric static FormatStyle &element(IO &IO, std::vector<FormatStyle> &Seq, 12200b57cec5SDimitry Andric size_t Index) { 12210b57cec5SDimitry Andric if (Index >= Seq.size()) { 12220b57cec5SDimitry Andric assert(Index == Seq.size()); 12230b57cec5SDimitry Andric FormatStyle Template; 12240b57cec5SDimitry Andric if (!Seq.empty() && Seq[0].Language == FormatStyle::LK_None) { 12250b57cec5SDimitry Andric Template = Seq[0]; 12260b57cec5SDimitry Andric } else { 12270b57cec5SDimitry Andric Template = *((const FormatStyle *)IO.getContext()); 12280b57cec5SDimitry Andric Template.Language = FormatStyle::LK_None; 12290b57cec5SDimitry Andric } 12300b57cec5SDimitry Andric Seq.resize(Index + 1, Template); 12310b57cec5SDimitry Andric } 12320b57cec5SDimitry Andric return Seq[Index]; 12330b57cec5SDimitry Andric } 12340b57cec5SDimitry Andric }; 12350b57cec5SDimitry Andric } // namespace yaml 12360b57cec5SDimitry Andric } // namespace llvm 12370b57cec5SDimitry Andric 12380b57cec5SDimitry Andric namespace clang { 12390b57cec5SDimitry Andric namespace format { 12400b57cec5SDimitry Andric 12410b57cec5SDimitry Andric const std::error_category &getParseCategory() { 12420b57cec5SDimitry Andric static const ParseErrorCategory C{}; 12430b57cec5SDimitry Andric return C; 12440b57cec5SDimitry Andric } 12450b57cec5SDimitry Andric std::error_code make_error_code(ParseError e) { 12460b57cec5SDimitry Andric return std::error_code(static_cast<int>(e), getParseCategory()); 12470b57cec5SDimitry Andric } 12480b57cec5SDimitry Andric 1249*0fca6ea1SDimitry Andric inline llvm::Error make_string_error(const Twine &Message) { 12500b57cec5SDimitry Andric return llvm::make_error<llvm::StringError>(Message, 12510b57cec5SDimitry Andric llvm::inconvertibleErrorCode()); 12520b57cec5SDimitry Andric } 12530b57cec5SDimitry Andric 12540b57cec5SDimitry Andric const char *ParseErrorCategory::name() const noexcept { 12550b57cec5SDimitry Andric return "clang-format.parse_error"; 12560b57cec5SDimitry Andric } 12570b57cec5SDimitry Andric 12580b57cec5SDimitry Andric std::string ParseErrorCategory::message(int EV) const { 12590b57cec5SDimitry Andric switch (static_cast<ParseError>(EV)) { 12600b57cec5SDimitry Andric case ParseError::Success: 12610b57cec5SDimitry Andric return "Success"; 12620b57cec5SDimitry Andric case ParseError::Error: 12630b57cec5SDimitry Andric return "Invalid argument"; 12640b57cec5SDimitry Andric case ParseError::Unsuitable: 12650b57cec5SDimitry Andric return "Unsuitable"; 12665ffd83dbSDimitry Andric case ParseError::BinPackTrailingCommaConflict: 12675ffd83dbSDimitry Andric return "trailing comma insertion cannot be used with bin packing"; 1268349cc55cSDimitry Andric case ParseError::InvalidQualifierSpecified: 1269349cc55cSDimitry Andric return "Invalid qualifier specified in QualifierOrder"; 1270349cc55cSDimitry Andric case ParseError::DuplicateQualifierSpecified: 127181ad6265SDimitry Andric return "Duplicate qualifier specified in QualifierOrder"; 1272349cc55cSDimitry Andric case ParseError::MissingQualifierType: 127381ad6265SDimitry Andric return "Missing type in QualifierOrder"; 1274349cc55cSDimitry Andric case ParseError::MissingQualifierOrder: 127581ad6265SDimitry Andric return "Missing QualifierOrder"; 12760b57cec5SDimitry Andric } 12770b57cec5SDimitry Andric llvm_unreachable("unexpected parse error"); 12780b57cec5SDimitry Andric } 12790b57cec5SDimitry Andric 1280349cc55cSDimitry Andric static void expandPresetsBraceWrapping(FormatStyle &Expanded) { 1281349cc55cSDimitry Andric if (Expanded.BreakBeforeBraces == FormatStyle::BS_Custom) 1282349cc55cSDimitry Andric return; 12835ffd83dbSDimitry Andric Expanded.BraceWrapping = {/*AfterCaseLabel=*/false, 12845ffd83dbSDimitry Andric /*AfterClass=*/false, 12855ffd83dbSDimitry Andric /*AfterControlStatement=*/FormatStyle::BWACS_Never, 12865ffd83dbSDimitry Andric /*AfterEnum=*/false, 12875ffd83dbSDimitry Andric /*AfterFunction=*/false, 12885ffd83dbSDimitry Andric /*AfterNamespace=*/false, 12895ffd83dbSDimitry Andric /*AfterObjCDeclaration=*/false, 12905ffd83dbSDimitry Andric /*AfterStruct=*/false, 12915ffd83dbSDimitry Andric /*AfterUnion=*/false, 12925ffd83dbSDimitry Andric /*AfterExternBlock=*/false, 12935ffd83dbSDimitry Andric /*BeforeCatch=*/false, 12945ffd83dbSDimitry Andric /*BeforeElse=*/false, 12955ffd83dbSDimitry Andric /*BeforeLambdaBody=*/false, 12965ffd83dbSDimitry Andric /*BeforeWhile=*/false, 12975ffd83dbSDimitry Andric /*IndentBraces=*/false, 12985ffd83dbSDimitry Andric /*SplitEmptyFunction=*/true, 12995ffd83dbSDimitry Andric /*SplitEmptyRecord=*/true, 13005ffd83dbSDimitry Andric /*SplitEmptyNamespace=*/true}; 1301349cc55cSDimitry Andric switch (Expanded.BreakBeforeBraces) { 13020b57cec5SDimitry Andric case FormatStyle::BS_Linux: 13030b57cec5SDimitry Andric Expanded.BraceWrapping.AfterClass = true; 13040b57cec5SDimitry Andric Expanded.BraceWrapping.AfterFunction = true; 13050b57cec5SDimitry Andric Expanded.BraceWrapping.AfterNamespace = true; 13060b57cec5SDimitry Andric break; 13070b57cec5SDimitry Andric case FormatStyle::BS_Mozilla: 13080b57cec5SDimitry Andric Expanded.BraceWrapping.AfterClass = true; 13090b57cec5SDimitry Andric Expanded.BraceWrapping.AfterEnum = true; 13100b57cec5SDimitry Andric Expanded.BraceWrapping.AfterFunction = true; 13110b57cec5SDimitry Andric Expanded.BraceWrapping.AfterStruct = true; 13120b57cec5SDimitry Andric Expanded.BraceWrapping.AfterUnion = true; 13130b57cec5SDimitry Andric Expanded.BraceWrapping.AfterExternBlock = true; 13140b57cec5SDimitry Andric Expanded.BraceWrapping.SplitEmptyFunction = true; 13150b57cec5SDimitry Andric Expanded.BraceWrapping.SplitEmptyRecord = false; 13160b57cec5SDimitry Andric break; 13170b57cec5SDimitry Andric case FormatStyle::BS_Stroustrup: 13180b57cec5SDimitry Andric Expanded.BraceWrapping.AfterFunction = true; 13190b57cec5SDimitry Andric Expanded.BraceWrapping.BeforeCatch = true; 13200b57cec5SDimitry Andric Expanded.BraceWrapping.BeforeElse = true; 13210b57cec5SDimitry Andric break; 13220b57cec5SDimitry Andric case FormatStyle::BS_Allman: 13230b57cec5SDimitry Andric Expanded.BraceWrapping.AfterCaseLabel = true; 13240b57cec5SDimitry Andric Expanded.BraceWrapping.AfterClass = true; 1325a7dea167SDimitry Andric Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always; 1326a7dea167SDimitry Andric Expanded.BraceWrapping.AfterEnum = true; 1327a7dea167SDimitry Andric Expanded.BraceWrapping.AfterFunction = true; 1328a7dea167SDimitry Andric Expanded.BraceWrapping.AfterNamespace = true; 1329a7dea167SDimitry Andric Expanded.BraceWrapping.AfterObjCDeclaration = true; 1330a7dea167SDimitry Andric Expanded.BraceWrapping.AfterStruct = true; 1331a7dea167SDimitry Andric Expanded.BraceWrapping.AfterUnion = true; 1332a7dea167SDimitry Andric Expanded.BraceWrapping.AfterExternBlock = true; 1333a7dea167SDimitry Andric Expanded.BraceWrapping.BeforeCatch = true; 1334a7dea167SDimitry Andric Expanded.BraceWrapping.BeforeElse = true; 1335e8d8bef9SDimitry Andric Expanded.BraceWrapping.BeforeLambdaBody = true; 1336a7dea167SDimitry Andric break; 1337a7dea167SDimitry Andric case FormatStyle::BS_Whitesmiths: 1338a7dea167SDimitry Andric Expanded.BraceWrapping.AfterCaseLabel = true; 1339a7dea167SDimitry Andric Expanded.BraceWrapping.AfterClass = true; 1340a7dea167SDimitry Andric Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always; 13410b57cec5SDimitry Andric Expanded.BraceWrapping.AfterEnum = true; 13420b57cec5SDimitry Andric Expanded.BraceWrapping.AfterFunction = true; 13430b57cec5SDimitry Andric Expanded.BraceWrapping.AfterNamespace = true; 13440b57cec5SDimitry Andric Expanded.BraceWrapping.AfterObjCDeclaration = true; 13450b57cec5SDimitry Andric Expanded.BraceWrapping.AfterStruct = true; 13460b57cec5SDimitry Andric Expanded.BraceWrapping.AfterExternBlock = true; 13470b57cec5SDimitry Andric Expanded.BraceWrapping.BeforeCatch = true; 13480b57cec5SDimitry Andric Expanded.BraceWrapping.BeforeElse = true; 13495ffd83dbSDimitry Andric Expanded.BraceWrapping.BeforeLambdaBody = true; 13500b57cec5SDimitry Andric break; 13510b57cec5SDimitry Andric case FormatStyle::BS_GNU: 13525ffd83dbSDimitry Andric Expanded.BraceWrapping = { 13535ffd83dbSDimitry Andric /*AfterCaseLabel=*/true, 13545ffd83dbSDimitry Andric /*AfterClass=*/true, 13555ffd83dbSDimitry Andric /*AfterControlStatement=*/FormatStyle::BWACS_Always, 13565ffd83dbSDimitry Andric /*AfterEnum=*/true, 13575ffd83dbSDimitry Andric /*AfterFunction=*/true, 13585ffd83dbSDimitry Andric /*AfterNamespace=*/true, 13595ffd83dbSDimitry Andric /*AfterObjCDeclaration=*/true, 13605ffd83dbSDimitry Andric /*AfterStruct=*/true, 13615ffd83dbSDimitry Andric /*AfterUnion=*/true, 13625ffd83dbSDimitry Andric /*AfterExternBlock=*/true, 13635ffd83dbSDimitry Andric /*BeforeCatch=*/true, 13645ffd83dbSDimitry Andric /*BeforeElse=*/true, 13655ffd83dbSDimitry Andric /*BeforeLambdaBody=*/false, 13665ffd83dbSDimitry Andric /*BeforeWhile=*/true, 13675ffd83dbSDimitry Andric /*IndentBraces=*/true, 13685ffd83dbSDimitry Andric /*SplitEmptyFunction=*/true, 13695ffd83dbSDimitry Andric /*SplitEmptyRecord=*/true, 13705ffd83dbSDimitry Andric /*SplitEmptyNamespace=*/true}; 13710b57cec5SDimitry Andric break; 13720b57cec5SDimitry Andric case FormatStyle::BS_WebKit: 13730b57cec5SDimitry Andric Expanded.BraceWrapping.AfterFunction = true; 13740b57cec5SDimitry Andric break; 13750b57cec5SDimitry Andric default: 13760b57cec5SDimitry Andric break; 13770b57cec5SDimitry Andric } 1378349cc55cSDimitry Andric } 1379349cc55cSDimitry Andric 1380349cc55cSDimitry Andric static void expandPresetsSpaceBeforeParens(FormatStyle &Expanded) { 1381349cc55cSDimitry Andric if (Expanded.SpaceBeforeParens == FormatStyle::SBPO_Custom) 1382349cc55cSDimitry Andric return; 1383349cc55cSDimitry Andric // Reset all flags 1384349cc55cSDimitry Andric Expanded.SpaceBeforeParensOptions = {}; 1385b3edf446SDimitry Andric Expanded.SpaceBeforeParensOptions.AfterPlacementOperator = true; 1386349cc55cSDimitry Andric 1387349cc55cSDimitry Andric switch (Expanded.SpaceBeforeParens) { 1388349cc55cSDimitry Andric case FormatStyle::SBPO_ControlStatements: 1389349cc55cSDimitry Andric Expanded.SpaceBeforeParensOptions.AfterControlStatements = true; 1390349cc55cSDimitry Andric Expanded.SpaceBeforeParensOptions.AfterForeachMacros = true; 1391349cc55cSDimitry Andric Expanded.SpaceBeforeParensOptions.AfterIfMacros = true; 1392349cc55cSDimitry Andric break; 1393349cc55cSDimitry Andric case FormatStyle::SBPO_ControlStatementsExceptControlMacros: 1394349cc55cSDimitry Andric Expanded.SpaceBeforeParensOptions.AfterControlStatements = true; 1395349cc55cSDimitry Andric break; 1396349cc55cSDimitry Andric case FormatStyle::SBPO_NonEmptyParentheses: 1397349cc55cSDimitry Andric Expanded.SpaceBeforeParensOptions.BeforeNonEmptyParentheses = true; 1398349cc55cSDimitry Andric break; 1399349cc55cSDimitry Andric default: 1400349cc55cSDimitry Andric break; 1401349cc55cSDimitry Andric } 14020b57cec5SDimitry Andric } 14030b57cec5SDimitry Andric 140406c3fb27SDimitry Andric static void expandPresetsSpacesInParens(FormatStyle &Expanded) { 140506c3fb27SDimitry Andric if (Expanded.SpacesInParens == FormatStyle::SIPO_Custom) 140606c3fb27SDimitry Andric return; 140706c3fb27SDimitry Andric assert(Expanded.SpacesInParens == FormatStyle::SIPO_Never); 140806c3fb27SDimitry Andric // Reset all flags 140906c3fb27SDimitry Andric Expanded.SpacesInParensOptions = {}; 141006c3fb27SDimitry Andric } 141106c3fb27SDimitry Andric 14120b57cec5SDimitry Andric FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { 14130b57cec5SDimitry Andric FormatStyle LLVMStyle; 14140b57cec5SDimitry Andric LLVMStyle.AccessModifierOffset = -2; 14150b57cec5SDimitry Andric LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align; 1416fe6060f1SDimitry Andric LLVMStyle.AlignArrayOfStructures = FormatStyle::AIAS_None; 141781ad6265SDimitry Andric LLVMStyle.AlignConsecutiveAssignments = {}; 141881ad6265SDimitry Andric LLVMStyle.AlignConsecutiveAssignments.AcrossComments = false; 1419*0fca6ea1SDimitry Andric LLVMStyle.AlignConsecutiveAssignments.AcrossEmptyLines = false; 142081ad6265SDimitry Andric LLVMStyle.AlignConsecutiveAssignments.AlignCompound = false; 1421297eecfbSDimitry Andric LLVMStyle.AlignConsecutiveAssignments.AlignFunctionPointers = false; 1422*0fca6ea1SDimitry Andric LLVMStyle.AlignConsecutiveAssignments.Enabled = false; 142381ad6265SDimitry Andric LLVMStyle.AlignConsecutiveAssignments.PadOperators = true; 142481ad6265SDimitry Andric LLVMStyle.AlignConsecutiveBitFields = {}; 142581ad6265SDimitry Andric LLVMStyle.AlignConsecutiveDeclarations = {}; 142681ad6265SDimitry Andric LLVMStyle.AlignConsecutiveMacros = {}; 142706c3fb27SDimitry Andric LLVMStyle.AlignConsecutiveShortCaseStatements = {}; 1428*0fca6ea1SDimitry Andric LLVMStyle.AlignConsecutiveTableGenBreakingDAGArgColons = {}; 1429*0fca6ea1SDimitry Andric LLVMStyle.AlignConsecutiveTableGenCondOperatorColons = {}; 1430*0fca6ea1SDimitry Andric LLVMStyle.AlignConsecutiveTableGenDefinitionColons = {}; 1431*0fca6ea1SDimitry Andric LLVMStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right; 1432*0fca6ea1SDimitry Andric LLVMStyle.AlignOperands = FormatStyle::OAS_Align; 1433bdd1243dSDimitry Andric LLVMStyle.AlignTrailingComments = {}; 1434bdd1243dSDimitry Andric LLVMStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Always; 1435bdd1243dSDimitry Andric LLVMStyle.AlignTrailingComments.OverEmptyLines = 0; 14360b57cec5SDimitry Andric LLVMStyle.AllowAllArgumentsOnNextLine = true; 14370b57cec5SDimitry Andric LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true; 1438*0fca6ea1SDimitry Andric LLVMStyle.AllowBreakBeforeNoexceptSpecifier = FormatStyle::BBNSS_Never; 1439a7dea167SDimitry Andric LLVMStyle.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never; 1440*0fca6ea1SDimitry Andric LLVMStyle.AllowShortCaseExpressionOnASingleLine = true; 14410b57cec5SDimitry Andric LLVMStyle.AllowShortCaseLabelsOnASingleLine = false; 14425f757f3fSDimitry Andric LLVMStyle.AllowShortCompoundRequirementOnASingleLine = true; 1443bdd1243dSDimitry Andric LLVMStyle.AllowShortEnumsOnASingleLine = true; 1444bdd1243dSDimitry Andric LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; 14450b57cec5SDimitry Andric LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 14460b57cec5SDimitry Andric LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All; 14470b57cec5SDimitry Andric LLVMStyle.AllowShortLoopsOnASingleLine = false; 14480b57cec5SDimitry Andric LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None; 14490b57cec5SDimitry Andric LLVMStyle.AlwaysBreakBeforeMultilineStrings = false; 1450e8d8bef9SDimitry Andric LLVMStyle.AttributeMacros.push_back("__capability"); 14510b57cec5SDimitry Andric LLVMStyle.BinPackArguments = true; 14520b57cec5SDimitry Andric LLVMStyle.BinPackParameters = true; 1453*0fca6ea1SDimitry Andric LLVMStyle.BitFieldColonSpacing = FormatStyle::BFCS_Both; 145406c3fb27SDimitry Andric LLVMStyle.BracedInitializerIndentWidth = std::nullopt; 14555ffd83dbSDimitry Andric LLVMStyle.BraceWrapping = {/*AfterCaseLabel=*/false, 14565ffd83dbSDimitry Andric /*AfterClass=*/false, 14575ffd83dbSDimitry Andric /*AfterControlStatement=*/FormatStyle::BWACS_Never, 14585ffd83dbSDimitry Andric /*AfterEnum=*/false, 14595ffd83dbSDimitry Andric /*AfterFunction=*/false, 14605ffd83dbSDimitry Andric /*AfterNamespace=*/false, 14615ffd83dbSDimitry Andric /*AfterObjCDeclaration=*/false, 14625ffd83dbSDimitry Andric /*AfterStruct=*/false, 14635ffd83dbSDimitry Andric /*AfterUnion=*/false, 14645ffd83dbSDimitry Andric /*AfterExternBlock=*/false, 14655ffd83dbSDimitry Andric /*BeforeCatch=*/false, 14665ffd83dbSDimitry Andric /*BeforeElse=*/false, 14675ffd83dbSDimitry Andric /*BeforeLambdaBody=*/false, 14685ffd83dbSDimitry Andric /*BeforeWhile=*/false, 14695ffd83dbSDimitry Andric /*IndentBraces=*/false, 14705ffd83dbSDimitry Andric /*SplitEmptyFunction=*/true, 14715ffd83dbSDimitry Andric /*SplitEmptyRecord=*/true, 14725ffd83dbSDimitry Andric /*SplitEmptyNamespace=*/true}; 14735f757f3fSDimitry Andric LLVMStyle.BreakAdjacentStringLiterals = true; 14745f757f3fSDimitry Andric LLVMStyle.BreakAfterAttributes = FormatStyle::ABS_Leave; 14750b57cec5SDimitry Andric LLVMStyle.BreakAfterJavaFieldAnnotations = false; 1476*0fca6ea1SDimitry Andric LLVMStyle.BreakAfterReturnType = FormatStyle::RTBS_None; 1477bdd1243dSDimitry Andric LLVMStyle.BreakArrays = true; 1478bdd1243dSDimitry Andric LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None; 1479bdd1243dSDimitry Andric LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach; 1480bdd1243dSDimitry Andric LLVMStyle.BreakBeforeConceptDeclarations = FormatStyle::BBCDS_Always; 1481bdd1243dSDimitry Andric LLVMStyle.BreakBeforeInlineASMColon = FormatStyle::BBIAS_OnlyMultiline; 1482bdd1243dSDimitry Andric LLVMStyle.BreakBeforeTernaryOperators = true; 14830b57cec5SDimitry Andric LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon; 1484*0fca6ea1SDimitry Andric LLVMStyle.BreakFunctionDefinitionParameters = false; 14850b57cec5SDimitry Andric LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon; 14860b57cec5SDimitry Andric LLVMStyle.BreakStringLiterals = true; 1487*0fca6ea1SDimitry Andric LLVMStyle.BreakTemplateDeclarations = FormatStyle::BTDS_MultiLine; 14880b57cec5SDimitry Andric LLVMStyle.ColumnLimit = 80; 14890b57cec5SDimitry Andric LLVMStyle.CommentPragmas = "^ IWYU pragma:"; 14900b57cec5SDimitry Andric LLVMStyle.CompactNamespaces = false; 14910b57cec5SDimitry Andric LLVMStyle.ConstructorInitializerIndentWidth = 4; 14920b57cec5SDimitry Andric LLVMStyle.ContinuationIndentWidth = 4; 14930b57cec5SDimitry Andric LLVMStyle.Cpp11BracedListStyle = true; 14940b57cec5SDimitry Andric LLVMStyle.DerivePointerAlignment = false; 1495bdd1243dSDimitry Andric LLVMStyle.DisableFormat = false; 1496fe6060f1SDimitry Andric LLVMStyle.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Never; 1497e8d8bef9SDimitry Andric LLVMStyle.EmptyLineBeforeAccessModifier = FormatStyle::ELBAMS_LogicalBlock; 14980b57cec5SDimitry Andric LLVMStyle.ExperimentalAutoDetectBinPacking = false; 14990b57cec5SDimitry Andric LLVMStyle.FixNamespaceComments = true; 15000b57cec5SDimitry Andric LLVMStyle.ForEachMacros.push_back("foreach"); 15010b57cec5SDimitry Andric LLVMStyle.ForEachMacros.push_back("Q_FOREACH"); 15020b57cec5SDimitry Andric LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH"); 1503fe6060f1SDimitry Andric LLVMStyle.IfMacros.push_back("KJ_IF_MAYBE"); 1504*0fca6ea1SDimitry Andric LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve; 15050b57cec5SDimitry Andric LLVMStyle.IncludeStyle.IncludeCategories = { 1506e8d8bef9SDimitry Andric {"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0, false}, 1507e8d8bef9SDimitry Andric {"^(<|\"(gtest|gmock|isl|json)/)", 3, 0, false}, 1508e8d8bef9SDimitry Andric {".*", 1, 0, false}}; 15090b57cec5SDimitry Andric LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$"; 1510*0fca6ea1SDimitry Andric LLVMStyle.IncludeStyle.MainIncludeChar = tooling::IncludeStyle::MICD_Quote; 1511fe6060f1SDimitry Andric LLVMStyle.IndentAccessModifiers = false; 15125ffd83dbSDimitry Andric LLVMStyle.IndentCaseBlocks = false; 1513*0fca6ea1SDimitry Andric LLVMStyle.IndentCaseLabels = false; 1514bdd1243dSDimitry Andric LLVMStyle.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; 1515a7dea167SDimitry Andric LLVMStyle.IndentGotoLabels = true; 15160b57cec5SDimitry Andric LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None; 151781ad6265SDimitry Andric LLVMStyle.IndentRequiresClause = true; 15180b57cec5SDimitry Andric LLVMStyle.IndentWidth = 2; 1519bdd1243dSDimitry Andric LLVMStyle.IndentWrappedFunctionNames = false; 1520*0fca6ea1SDimitry Andric LLVMStyle.InheritsParentConfig = false; 152181ad6265SDimitry Andric LLVMStyle.InsertBraces = false; 1522bdd1243dSDimitry Andric LLVMStyle.InsertNewlineAtEOF = false; 15235ffd83dbSDimitry Andric LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None; 15241ac55f4cSDimitry Andric LLVMStyle.IntegerLiteralSeparator = { 15251ac55f4cSDimitry Andric /*Binary=*/0, /*BinaryMinDigits=*/0, 15261ac55f4cSDimitry Andric /*Decimal=*/0, /*DecimalMinDigits=*/0, 15271ac55f4cSDimitry Andric /*Hex=*/0, /*HexMinDigits=*/0}; 15280b57cec5SDimitry Andric LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave; 15290b57cec5SDimitry Andric LLVMStyle.JavaScriptWrapImports = true; 1530*0fca6ea1SDimitry Andric LLVMStyle.KeepEmptyLines = { 1531*0fca6ea1SDimitry Andric /*AtEndOfFile=*/false, 1532*0fca6ea1SDimitry Andric /*AtStartOfBlock=*/true, 1533*0fca6ea1SDimitry Andric /*AtStartOfFile=*/true, 1534*0fca6ea1SDimitry Andric }; 1535bdd1243dSDimitry Andric LLVMStyle.LambdaBodyIndentation = FormatStyle::LBI_Signature; 1536*0fca6ea1SDimitry Andric LLVMStyle.Language = Language; 1537bdd1243dSDimitry Andric LLVMStyle.LineEnding = FormatStyle::LE_DeriveLF; 1538bdd1243dSDimitry Andric LLVMStyle.MaxEmptyLinesToKeep = 1; 15390b57cec5SDimitry Andric LLVMStyle.NamespaceIndentation = FormatStyle::NI_None; 15400b57cec5SDimitry Andric LLVMStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Auto; 15410b57cec5SDimitry Andric LLVMStyle.ObjCBlockIndentWidth = 2; 15425ffd83dbSDimitry Andric LLVMStyle.ObjCBreakBeforeNestedBlockParam = true; 15430b57cec5SDimitry Andric LLVMStyle.ObjCSpaceAfterProperty = false; 15440b57cec5SDimitry Andric LLVMStyle.ObjCSpaceBeforeProtocolList = true; 1545bdd1243dSDimitry Andric LLVMStyle.PackConstructorInitializers = FormatStyle::PCIS_BinPack; 15460b57cec5SDimitry Andric LLVMStyle.PointerAlignment = FormatStyle::PAS_Right; 1547bdd1243dSDimitry Andric LLVMStyle.PPIndentWidth = -1; 1548bdd1243dSDimitry Andric LLVMStyle.QualifierAlignment = FormatStyle::QAS_Leave; 1549fe6060f1SDimitry Andric LLVMStyle.ReferenceAlignment = FormatStyle::RAS_Pointer; 15500b57cec5SDimitry Andric LLVMStyle.ReflowComments = true; 155104eeddc0SDimitry Andric LLVMStyle.RemoveBracesLLVM = false; 155206c3fb27SDimitry Andric LLVMStyle.RemoveParentheses = FormatStyle::RPS_Leave; 1553bdd1243dSDimitry Andric LLVMStyle.RemoveSemicolon = false; 1554bdd1243dSDimitry Andric LLVMStyle.RequiresClausePosition = FormatStyle::RCPS_OwnLine; 1555bdd1243dSDimitry Andric LLVMStyle.RequiresExpressionIndentation = FormatStyle::REI_OuterScope; 1556bdd1243dSDimitry Andric LLVMStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Leave; 1557bdd1243dSDimitry Andric LLVMStyle.ShortNamespaceLines = 1; 15587a6dacacSDimitry Andric LLVMStyle.SkipMacroDefinitionBody = false; 1559bdd1243dSDimitry Andric LLVMStyle.SortIncludes = FormatStyle::SI_CaseSensitive; 1560bdd1243dSDimitry Andric LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before; 1561bdd1243dSDimitry Andric LLVMStyle.SortUsingDeclarations = FormatStyle::SUD_LexicographicNumeric; 15620b57cec5SDimitry Andric LLVMStyle.SpaceAfterCStyleCast = false; 15630b57cec5SDimitry Andric LLVMStyle.SpaceAfterLogicalNot = false; 15640b57cec5SDimitry Andric LLVMStyle.SpaceAfterTemplateKeyword = true; 1565e8d8bef9SDimitry Andric LLVMStyle.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Default; 1566*0fca6ea1SDimitry Andric LLVMStyle.SpaceBeforeAssignmentOperators = true; 1567e8d8bef9SDimitry Andric LLVMStyle.SpaceBeforeCaseColon = false; 1568*0fca6ea1SDimitry Andric LLVMStyle.SpaceBeforeCpp11BracedList = false; 15690b57cec5SDimitry Andric LLVMStyle.SpaceBeforeCtorInitializerColon = true; 15700b57cec5SDimitry Andric LLVMStyle.SpaceBeforeInheritanceColon = true; 157106c3fb27SDimitry Andric LLVMStyle.SpaceBeforeJsonColon = false; 15720b57cec5SDimitry Andric LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements; 157381ad6265SDimitry Andric LLVMStyle.SpaceBeforeParensOptions = {}; 1574349cc55cSDimitry Andric LLVMStyle.SpaceBeforeParensOptions.AfterControlStatements = true; 1575349cc55cSDimitry Andric LLVMStyle.SpaceBeforeParensOptions.AfterForeachMacros = true; 1576349cc55cSDimitry Andric LLVMStyle.SpaceBeforeParensOptions.AfterIfMacros = true; 15770b57cec5SDimitry Andric LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true; 1578480093f4SDimitry Andric LLVMStyle.SpaceBeforeSquareBrackets = false; 1579bdd1243dSDimitry Andric LLVMStyle.SpaceInEmptyBlock = false; 1580bdd1243dSDimitry Andric LLVMStyle.SpacesBeforeTrailingComments = 1; 1581fe6060f1SDimitry Andric LLVMStyle.SpacesInAngles = FormatStyle::SIAS_Never; 1582bdd1243dSDimitry Andric LLVMStyle.SpacesInContainerLiterals = true; 1583bdd1243dSDimitry Andric LLVMStyle.SpacesInLineCommentPrefix = {/*Minimum=*/1, /*Maximum=*/-1u}; 158406c3fb27SDimitry Andric LLVMStyle.SpacesInParens = FormatStyle::SIPO_Never; 1585bdd1243dSDimitry Andric LLVMStyle.SpacesInSquareBrackets = false; 1586bdd1243dSDimitry Andric LLVMStyle.Standard = FormatStyle::LS_Latest; 1587bdd1243dSDimitry Andric LLVMStyle.StatementAttributeLikeMacros.push_back("Q_EMIT"); 1588bdd1243dSDimitry Andric LLVMStyle.StatementMacros.push_back("Q_UNUSED"); 1589bdd1243dSDimitry Andric LLVMStyle.StatementMacros.push_back("QT_REQUIRE_VERSION"); 1590*0fca6ea1SDimitry Andric LLVMStyle.TableGenBreakingDAGArgOperators = {}; 1591*0fca6ea1SDimitry Andric LLVMStyle.TableGenBreakInsideDAGArg = FormatStyle::DAS_DontBreak; 1592bdd1243dSDimitry Andric LLVMStyle.TabWidth = 8; 1593bdd1243dSDimitry Andric LLVMStyle.UseTab = FormatStyle::UT_Never; 159406c3fb27SDimitry Andric LLVMStyle.VerilogBreakBetweenInstancePorts = true; 1595bdd1243dSDimitry Andric LLVMStyle.WhitespaceSensitiveMacros.push_back("BOOST_PP_STRINGIZE"); 1596bdd1243dSDimitry Andric LLVMStyle.WhitespaceSensitiveMacros.push_back("CF_SWIFT_NAME"); 1597bdd1243dSDimitry Andric LLVMStyle.WhitespaceSensitiveMacros.push_back("NS_SWIFT_NAME"); 1598bdd1243dSDimitry Andric LLVMStyle.WhitespaceSensitiveMacros.push_back("PP_STRINGIZE"); 1599bdd1243dSDimitry Andric LLVMStyle.WhitespaceSensitiveMacros.push_back("STRINGIZE"); 16000b57cec5SDimitry Andric 16010b57cec5SDimitry Andric LLVMStyle.PenaltyBreakAssignment = prec::Assignment; 1602*0fca6ea1SDimitry Andric LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19; 16030b57cec5SDimitry Andric LLVMStyle.PenaltyBreakComment = 300; 16040b57cec5SDimitry Andric LLVMStyle.PenaltyBreakFirstLessLess = 120; 160504eeddc0SDimitry Andric LLVMStyle.PenaltyBreakOpenParenthesis = 0; 16067a6dacacSDimitry Andric LLVMStyle.PenaltyBreakScopeResolution = 500; 1607*0fca6ea1SDimitry Andric LLVMStyle.PenaltyBreakString = 1000; 16080b57cec5SDimitry Andric LLVMStyle.PenaltyBreakTemplateDeclaration = prec::Relational; 1609*0fca6ea1SDimitry Andric LLVMStyle.PenaltyExcessCharacter = 1'000'000; 1610e8d8bef9SDimitry Andric LLVMStyle.PenaltyIndentedWhitespace = 0; 1611*0fca6ea1SDimitry Andric LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60; 16120b57cec5SDimitry Andric 16130b57cec5SDimitry Andric // Defaults that differ when not C++. 1614bdd1243dSDimitry Andric switch (Language) { 1615bdd1243dSDimitry Andric case FormatStyle::LK_TableGen: 16160b57cec5SDimitry Andric LLVMStyle.SpacesInContainerLiterals = false; 1617bdd1243dSDimitry Andric break; 1618bdd1243dSDimitry Andric case FormatStyle::LK_Json: 1619fe6060f1SDimitry Andric LLVMStyle.ColumnLimit = 0; 1620bdd1243dSDimitry Andric break; 1621bdd1243dSDimitry Andric case FormatStyle::LK_Verilog: 1622bdd1243dSDimitry Andric LLVMStyle.IndentCaseLabels = true; 162306c3fb27SDimitry Andric LLVMStyle.SpacesInContainerLiterals = false; 1624bdd1243dSDimitry Andric break; 1625bdd1243dSDimitry Andric default: 1626bdd1243dSDimitry Andric break; 1627bdd1243dSDimitry Andric } 16280b57cec5SDimitry Andric 16290b57cec5SDimitry Andric return LLVMStyle; 16300b57cec5SDimitry Andric } 16310b57cec5SDimitry Andric 16320b57cec5SDimitry Andric FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { 16330b57cec5SDimitry Andric if (Language == FormatStyle::LK_TextProto) { 16340b57cec5SDimitry Andric FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_Proto); 16350b57cec5SDimitry Andric GoogleStyle.Language = FormatStyle::LK_TextProto; 16360b57cec5SDimitry Andric 16370b57cec5SDimitry Andric return GoogleStyle; 16380b57cec5SDimitry Andric } 16390b57cec5SDimitry Andric 16400b57cec5SDimitry Andric FormatStyle GoogleStyle = getLLVMStyle(Language); 16410b57cec5SDimitry Andric 16420b57cec5SDimitry Andric GoogleStyle.AccessModifierOffset = -1; 16430b57cec5SDimitry Andric GoogleStyle.AlignEscapedNewlines = FormatStyle::ENAS_Left; 16440b57cec5SDimitry Andric GoogleStyle.AllowShortIfStatementsOnASingleLine = 16450b57cec5SDimitry Andric FormatStyle::SIS_WithoutElse; 16460b57cec5SDimitry Andric GoogleStyle.AllowShortLoopsOnASingleLine = true; 16470b57cec5SDimitry Andric GoogleStyle.AlwaysBreakBeforeMultilineStrings = true; 1648*0fca6ea1SDimitry Andric GoogleStyle.BreakTemplateDeclarations = FormatStyle::BTDS_Yes; 16490b57cec5SDimitry Andric GoogleStyle.DerivePointerAlignment = true; 1650*0fca6ea1SDimitry Andric GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 1651e8d8bef9SDimitry Andric GoogleStyle.IncludeStyle.IncludeCategories = {{"^<ext/.*\\.h>", 2, 0, false}, 1652e8d8bef9SDimitry Andric {"^<.*\\.h>", 1, 0, false}, 1653e8d8bef9SDimitry Andric {"^<.*", 2, 0, false}, 1654e8d8bef9SDimitry Andric {".*", 3, 0, false}}; 16550b57cec5SDimitry Andric GoogleStyle.IncludeStyle.IncludeIsMainRegex = "([-_](test|unittest))?$"; 16560b57cec5SDimitry Andric GoogleStyle.IndentCaseLabels = true; 1657*0fca6ea1SDimitry Andric GoogleStyle.KeepEmptyLines.AtStartOfBlock = false; 16580b57cec5SDimitry Andric GoogleStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Never; 16590b57cec5SDimitry Andric GoogleStyle.ObjCSpaceAfterProperty = false; 16600b57cec5SDimitry Andric GoogleStyle.ObjCSpaceBeforeProtocolList = true; 1661349cc55cSDimitry Andric GoogleStyle.PackConstructorInitializers = FormatStyle::PCIS_NextLine; 16620b57cec5SDimitry Andric GoogleStyle.PointerAlignment = FormatStyle::PAS_Left; 16630b57cec5SDimitry Andric GoogleStyle.RawStringFormats = { 16640b57cec5SDimitry Andric { 16650b57cec5SDimitry Andric FormatStyle::LK_Cpp, 16660b57cec5SDimitry Andric /*Delimiters=*/ 16670b57cec5SDimitry Andric { 16680b57cec5SDimitry Andric "cc", 16690b57cec5SDimitry Andric "CC", 16700b57cec5SDimitry Andric "cpp", 16710b57cec5SDimitry Andric "Cpp", 16720b57cec5SDimitry Andric "CPP", 16730b57cec5SDimitry Andric "c++", 16740b57cec5SDimitry Andric "C++", 16750b57cec5SDimitry Andric }, 16760b57cec5SDimitry Andric /*EnclosingFunctionNames=*/ 16770b57cec5SDimitry Andric {}, 16780b57cec5SDimitry Andric /*CanonicalDelimiter=*/"", 16790b57cec5SDimitry Andric /*BasedOnStyle=*/"google", 16800b57cec5SDimitry Andric }, 16810b57cec5SDimitry Andric { 16820b57cec5SDimitry Andric FormatStyle::LK_TextProto, 16830b57cec5SDimitry Andric /*Delimiters=*/ 16840b57cec5SDimitry Andric { 16850b57cec5SDimitry Andric "pb", 16860b57cec5SDimitry Andric "PB", 16870b57cec5SDimitry Andric "proto", 16880b57cec5SDimitry Andric "PROTO", 16890b57cec5SDimitry Andric }, 16900b57cec5SDimitry Andric /*EnclosingFunctionNames=*/ 16910b57cec5SDimitry Andric { 16920b57cec5SDimitry Andric "EqualsProto", 16930b57cec5SDimitry Andric "EquivToProto", 16940b57cec5SDimitry Andric "PARSE_PARTIAL_TEXT_PROTO", 16950b57cec5SDimitry Andric "PARSE_TEST_PROTO", 16960b57cec5SDimitry Andric "PARSE_TEXT_PROTO", 16970b57cec5SDimitry Andric "ParseTextOrDie", 16980b57cec5SDimitry Andric "ParseTextProtoOrDie", 16995ffd83dbSDimitry Andric "ParseTestProto", 17005ffd83dbSDimitry Andric "ParsePartialTestProto", 17010b57cec5SDimitry Andric }, 1702fe6060f1SDimitry Andric /*CanonicalDelimiter=*/"pb", 17030b57cec5SDimitry Andric /*BasedOnStyle=*/"google", 17040b57cec5SDimitry Andric }, 17050b57cec5SDimitry Andric }; 1706cb14a3feSDimitry Andric 17070b57cec5SDimitry Andric GoogleStyle.SpacesBeforeTrailingComments = 2; 17080b57cec5SDimitry Andric GoogleStyle.Standard = FormatStyle::LS_Auto; 17090b57cec5SDimitry Andric 17100b57cec5SDimitry Andric GoogleStyle.PenaltyBreakBeforeFirstCallParameter = 1; 1711*0fca6ea1SDimitry Andric GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200; 17120b57cec5SDimitry Andric 17130b57cec5SDimitry Andric if (Language == FormatStyle::LK_Java) { 17140b57cec5SDimitry Andric GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign; 17155ffd83dbSDimitry Andric GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign; 1716bdd1243dSDimitry Andric GoogleStyle.AlignTrailingComments = {}; 1717bdd1243dSDimitry Andric GoogleStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Never; 17180b57cec5SDimitry Andric GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; 17190b57cec5SDimitry Andric GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 17200b57cec5SDimitry Andric GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; 17210b57cec5SDimitry Andric GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment; 17220b57cec5SDimitry Andric GoogleStyle.ColumnLimit = 100; 17230b57cec5SDimitry Andric GoogleStyle.SpaceAfterCStyleCast = true; 17240b57cec5SDimitry Andric GoogleStyle.SpacesBeforeTrailingComments = 1; 17250b57cec5SDimitry Andric } else if (Language == FormatStyle::LK_JavaScript) { 17260b57cec5SDimitry Andric GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; 17275ffd83dbSDimitry Andric GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign; 17280b57cec5SDimitry Andric GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; 17295ffd83dbSDimitry Andric // TODO: still under discussion whether to switch to SLS_All. 17305ffd83dbSDimitry Andric GoogleStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty; 17310b57cec5SDimitry Andric GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; 17320b57cec5SDimitry Andric GoogleStyle.BreakBeforeTernaryOperators = false; 17335ffd83dbSDimitry Andric // taze:, triple slash directives (`/// <...`), tslint:, and @see, which is 17345ffd83dbSDimitry Andric // commonly followed by overlong URLs. 17355ffd83dbSDimitry Andric GoogleStyle.CommentPragmas = "(taze:|^/[ \t]*<|tslint:|@see)"; 17365ffd83dbSDimitry Andric // TODO: enable once decided, in particular re disabling bin packing. 17375ffd83dbSDimitry Andric // https://google.github.io/styleguide/jsguide.html#features-arrays-trailing-comma 17385ffd83dbSDimitry Andric // GoogleStyle.InsertTrailingCommas = FormatStyle::TCS_Wrapped; 1739*0fca6ea1SDimitry Andric GoogleStyle.JavaScriptQuotes = FormatStyle::JSQS_Single; 1740*0fca6ea1SDimitry Andric GoogleStyle.JavaScriptWrapImports = false; 17410b57cec5SDimitry Andric GoogleStyle.MaxEmptyLinesToKeep = 3; 17420b57cec5SDimitry Andric GoogleStyle.NamespaceIndentation = FormatStyle::NI_All; 17430b57cec5SDimitry Andric GoogleStyle.SpacesInContainerLiterals = false; 17440b57cec5SDimitry Andric } else if (Language == FormatStyle::LK_Proto) { 17450b57cec5SDimitry Andric GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; 17460b57cec5SDimitry Andric GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; 17470b57cec5SDimitry Andric // This affects protocol buffer options specifications and text protos. 17480b57cec5SDimitry Andric // Text protos are currently mostly formatted inside C++ raw string literals 17490b57cec5SDimitry Andric // and often the current breaking behavior of string literals is not 17500b57cec5SDimitry Andric // beneficial there. Investigate turning this on once proper string reflow 17510b57cec5SDimitry Andric // has been implemented. 17520b57cec5SDimitry Andric GoogleStyle.BreakStringLiterals = false; 1753*0fca6ea1SDimitry Andric GoogleStyle.Cpp11BracedListStyle = false; 1754*0fca6ea1SDimitry Andric GoogleStyle.SpacesInContainerLiterals = false; 17550b57cec5SDimitry Andric } else if (Language == FormatStyle::LK_ObjC) { 17560b57cec5SDimitry Andric GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; 17570b57cec5SDimitry Andric GoogleStyle.ColumnLimit = 100; 17580b57cec5SDimitry Andric // "Regroup" doesn't work well for ObjC yet (main header heuristic, 17590b57cec5SDimitry Andric // relationship between ObjC standard library headers and other heades, 17600b57cec5SDimitry Andric // #imports, etc.) 17610b57cec5SDimitry Andric GoogleStyle.IncludeStyle.IncludeBlocks = 17620b57cec5SDimitry Andric tooling::IncludeStyle::IBS_Preserve; 17635ffd83dbSDimitry Andric } else if (Language == FormatStyle::LK_CSharp) { 17645ffd83dbSDimitry Andric GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; 17655ffd83dbSDimitry Andric GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 17665ffd83dbSDimitry Andric GoogleStyle.BreakStringLiterals = false; 17675ffd83dbSDimitry Andric GoogleStyle.ColumnLimit = 100; 17685ffd83dbSDimitry Andric GoogleStyle.NamespaceIndentation = FormatStyle::NI_All; 17690b57cec5SDimitry Andric } 17700b57cec5SDimitry Andric 17710b57cec5SDimitry Andric return GoogleStyle; 17720b57cec5SDimitry Andric } 17730b57cec5SDimitry Andric 17740b57cec5SDimitry Andric FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) { 17750b57cec5SDimitry Andric FormatStyle ChromiumStyle = getGoogleStyle(Language); 1776a7dea167SDimitry Andric 1777a7dea167SDimitry Andric // Disable include reordering across blocks in Chromium code. 1778a7dea167SDimitry Andric // - clang-format tries to detect that foo.h is the "main" header for 1779a7dea167SDimitry Andric // foo.cc and foo_unittest.cc via IncludeIsMainRegex. However, Chromium 1780a7dea167SDimitry Andric // uses many other suffices (_win.cc, _mac.mm, _posix.cc, _browsertest.cc, 1781a7dea167SDimitry Andric // _private.cc, _impl.cc etc) in different permutations 1782a7dea167SDimitry Andric // (_win_browsertest.cc) so disable this until IncludeIsMainRegex has a 1783a7dea167SDimitry Andric // better default for Chromium code. 1784a7dea167SDimitry Andric // - The default for .cc and .mm files is different (r357695) for Google style 1785a7dea167SDimitry Andric // for the same reason. The plan is to unify this again once the main 1786a7dea167SDimitry Andric // header detection works for Google's ObjC code, but this hasn't happened 1787a7dea167SDimitry Andric // yet. Since Chromium has some ObjC code, switching Chromium is blocked 1788a7dea167SDimitry Andric // on that. 1789a7dea167SDimitry Andric // - Finally, "If include reordering is harmful, put things in different 1790a7dea167SDimitry Andric // blocks to prevent it" has been a recommendation for a long time that 1791a7dea167SDimitry Andric // people are used to. We'll need a dev education push to change this to 1792a7dea167SDimitry Andric // "If include reordering is harmful, put things in a different block and 1793a7dea167SDimitry Andric // _prepend that with a comment_ to prevent it" before changing behavior. 1794a7dea167SDimitry Andric ChromiumStyle.IncludeStyle.IncludeBlocks = 1795a7dea167SDimitry Andric tooling::IncludeStyle::IBS_Preserve; 1796a7dea167SDimitry Andric 17970b57cec5SDimitry Andric if (Language == FormatStyle::LK_Java) { 17980b57cec5SDimitry Andric ChromiumStyle.AllowShortIfStatementsOnASingleLine = 17990b57cec5SDimitry Andric FormatStyle::SIS_WithoutElse; 18000b57cec5SDimitry Andric ChromiumStyle.BreakAfterJavaFieldAnnotations = true; 18010b57cec5SDimitry Andric ChromiumStyle.ContinuationIndentWidth = 8; 18020b57cec5SDimitry Andric ChromiumStyle.IndentWidth = 4; 18030b57cec5SDimitry Andric // See styleguide for import groups: 1804349cc55cSDimitry Andric // https://chromium.googlesource.com/chromium/src/+/refs/heads/main/styleguide/java/java.md#Import-Order 18050b57cec5SDimitry Andric ChromiumStyle.JavaImportGroups = { 18060b57cec5SDimitry Andric "android", 18070b57cec5SDimitry Andric "androidx", 18080b57cec5SDimitry Andric "com", 18090b57cec5SDimitry Andric "dalvik", 18100b57cec5SDimitry Andric "junit", 18110b57cec5SDimitry Andric "org", 18120b57cec5SDimitry Andric "com.google.android.apps.chrome", 18130b57cec5SDimitry Andric "org.chromium", 18140b57cec5SDimitry Andric "java", 18150b57cec5SDimitry Andric "javax", 18160b57cec5SDimitry Andric }; 1817fe6060f1SDimitry Andric ChromiumStyle.SortIncludes = FormatStyle::SI_CaseSensitive; 18180b57cec5SDimitry Andric } else if (Language == FormatStyle::LK_JavaScript) { 18190b57cec5SDimitry Andric ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 18200b57cec5SDimitry Andric ChromiumStyle.AllowShortLoopsOnASingleLine = false; 18210b57cec5SDimitry Andric } else { 18220b57cec5SDimitry Andric ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false; 18230b57cec5SDimitry Andric ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; 18240b57cec5SDimitry Andric ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 18250b57cec5SDimitry Andric ChromiumStyle.AllowShortLoopsOnASingleLine = false; 18260b57cec5SDimitry Andric ChromiumStyle.BinPackParameters = false; 18270b57cec5SDimitry Andric ChromiumStyle.DerivePointerAlignment = false; 18280b57cec5SDimitry Andric if (Language == FormatStyle::LK_ObjC) 18290b57cec5SDimitry Andric ChromiumStyle.ColumnLimit = 80; 18300b57cec5SDimitry Andric } 18310b57cec5SDimitry Andric return ChromiumStyle; 18320b57cec5SDimitry Andric } 18330b57cec5SDimitry Andric 18340b57cec5SDimitry Andric FormatStyle getMozillaStyle() { 18350b57cec5SDimitry Andric FormatStyle MozillaStyle = getLLVMStyle(); 18360b57cec5SDimitry Andric MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false; 18370b57cec5SDimitry Andric MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; 18380b57cec5SDimitry Andric MozillaStyle.AlwaysBreakAfterDefinitionReturnType = 18390b57cec5SDimitry Andric FormatStyle::DRTBS_TopLevel; 18400b57cec5SDimitry Andric MozillaStyle.BinPackArguments = false; 1841*0fca6ea1SDimitry Andric MozillaStyle.BinPackParameters = false; 1842*0fca6ea1SDimitry Andric MozillaStyle.BreakAfterReturnType = FormatStyle::RTBS_TopLevel; 18430b57cec5SDimitry Andric MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla; 18440b57cec5SDimitry Andric MozillaStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma; 18450b57cec5SDimitry Andric MozillaStyle.BreakInheritanceList = FormatStyle::BILS_BeforeComma; 1846*0fca6ea1SDimitry Andric MozillaStyle.BreakTemplateDeclarations = FormatStyle::BTDS_Yes; 18470b57cec5SDimitry Andric MozillaStyle.ConstructorInitializerIndentWidth = 2; 18480b57cec5SDimitry Andric MozillaStyle.ContinuationIndentWidth = 2; 18490b57cec5SDimitry Andric MozillaStyle.Cpp11BracedListStyle = false; 18500b57cec5SDimitry Andric MozillaStyle.FixNamespaceComments = false; 18510b57cec5SDimitry Andric MozillaStyle.IndentCaseLabels = true; 18520b57cec5SDimitry Andric MozillaStyle.ObjCSpaceAfterProperty = true; 18530b57cec5SDimitry Andric MozillaStyle.ObjCSpaceBeforeProtocolList = false; 18540b57cec5SDimitry Andric MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200; 18550b57cec5SDimitry Andric MozillaStyle.PointerAlignment = FormatStyle::PAS_Left; 18560b57cec5SDimitry Andric MozillaStyle.SpaceAfterTemplateKeyword = false; 18570b57cec5SDimitry Andric return MozillaStyle; 18580b57cec5SDimitry Andric } 18590b57cec5SDimitry Andric 18600b57cec5SDimitry Andric FormatStyle getWebKitStyle() { 18610b57cec5SDimitry Andric FormatStyle Style = getLLVMStyle(); 18620b57cec5SDimitry Andric Style.AccessModifierOffset = -4; 18630b57cec5SDimitry Andric Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign; 18645ffd83dbSDimitry Andric Style.AlignOperands = FormatStyle::OAS_DontAlign; 1865bdd1243dSDimitry Andric Style.AlignTrailingComments = {}; 1866bdd1243dSDimitry Andric Style.AlignTrailingComments.Kind = FormatStyle::TCAS_Never; 1867a7dea167SDimitry Andric Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty; 18680b57cec5SDimitry Andric Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; 18690b57cec5SDimitry Andric Style.BreakBeforeBraces = FormatStyle::BS_WebKit; 18700b57cec5SDimitry Andric Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma; 18710b57cec5SDimitry Andric Style.ColumnLimit = 0; 1872*0fca6ea1SDimitry Andric Style.Cpp11BracedListStyle = false; 18730b57cec5SDimitry Andric Style.FixNamespaceComments = false; 18740b57cec5SDimitry Andric Style.IndentWidth = 4; 18750b57cec5SDimitry Andric Style.NamespaceIndentation = FormatStyle::NI_Inner; 18760b57cec5SDimitry Andric Style.ObjCBlockIndentWidth = 4; 18770b57cec5SDimitry Andric Style.ObjCSpaceAfterProperty = true; 18780b57cec5SDimitry Andric Style.PointerAlignment = FormatStyle::PAS_Left; 18790b57cec5SDimitry Andric Style.SpaceBeforeCpp11BracedList = true; 1880a7dea167SDimitry Andric Style.SpaceInEmptyBlock = true; 18810b57cec5SDimitry Andric return Style; 18820b57cec5SDimitry Andric } 18830b57cec5SDimitry Andric 18840b57cec5SDimitry Andric FormatStyle getGNUStyle() { 18850b57cec5SDimitry Andric FormatStyle Style = getLLVMStyle(); 18860b57cec5SDimitry Andric Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All; 1887*0fca6ea1SDimitry Andric Style.BreakAfterReturnType = FormatStyle::RTBS_AllDefinitions; 18880b57cec5SDimitry Andric Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; 18890b57cec5SDimitry Andric Style.BreakBeforeBraces = FormatStyle::BS_GNU; 18900b57cec5SDimitry Andric Style.BreakBeforeTernaryOperators = true; 18910b57cec5SDimitry Andric Style.ColumnLimit = 79; 1892*0fca6ea1SDimitry Andric Style.Cpp11BracedListStyle = false; 18930b57cec5SDimitry Andric Style.FixNamespaceComments = false; 18940b57cec5SDimitry Andric Style.SpaceBeforeParens = FormatStyle::SBPO_Always; 18950b57cec5SDimitry Andric Style.Standard = FormatStyle::LS_Cpp03; 18960b57cec5SDimitry Andric return Style; 18970b57cec5SDimitry Andric } 18980b57cec5SDimitry Andric 18990b57cec5SDimitry Andric FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language) { 1900a7dea167SDimitry Andric FormatStyle Style = getLLVMStyle(Language); 19010b57cec5SDimitry Andric Style.ColumnLimit = 120; 19020b57cec5SDimitry Andric Style.TabWidth = 4; 19030b57cec5SDimitry Andric Style.IndentWidth = 4; 19040b57cec5SDimitry Andric Style.UseTab = FormatStyle::UT_Never; 19050b57cec5SDimitry Andric Style.BreakBeforeBraces = FormatStyle::BS_Custom; 19060b57cec5SDimitry Andric Style.BraceWrapping.AfterClass = true; 1907a7dea167SDimitry Andric Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always; 19080b57cec5SDimitry Andric Style.BraceWrapping.AfterEnum = true; 19090b57cec5SDimitry Andric Style.BraceWrapping.AfterFunction = true; 19100b57cec5SDimitry Andric Style.BraceWrapping.AfterNamespace = true; 19110b57cec5SDimitry Andric Style.BraceWrapping.AfterObjCDeclaration = true; 19120b57cec5SDimitry Andric Style.BraceWrapping.AfterStruct = true; 19130b57cec5SDimitry Andric Style.BraceWrapping.AfterExternBlock = true; 19140b57cec5SDimitry Andric Style.BraceWrapping.BeforeCatch = true; 19150b57cec5SDimitry Andric Style.BraceWrapping.BeforeElse = true; 19165ffd83dbSDimitry Andric Style.BraceWrapping.BeforeWhile = false; 19170b57cec5SDimitry Andric Style.PenaltyReturnTypeOnItsOwnLine = 1000; 19185ffd83dbSDimitry Andric Style.AllowShortEnumsOnASingleLine = false; 19190b57cec5SDimitry Andric Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; 19200b57cec5SDimitry Andric Style.AllowShortCaseLabelsOnASingleLine = false; 19210b57cec5SDimitry Andric Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 19220b57cec5SDimitry Andric Style.AllowShortLoopsOnASingleLine = false; 1923a7dea167SDimitry Andric Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None; 1924*0fca6ea1SDimitry Andric Style.BreakAfterReturnType = FormatStyle::RTBS_None; 19250b57cec5SDimitry Andric return Style; 19260b57cec5SDimitry Andric } 19270b57cec5SDimitry Andric 19285f757f3fSDimitry Andric FormatStyle getClangFormatStyle() { 19295f757f3fSDimitry Andric FormatStyle Style = getLLVMStyle(); 19305f757f3fSDimitry Andric Style.InsertBraces = true; 19315f757f3fSDimitry Andric Style.InsertNewlineAtEOF = true; 1932*0fca6ea1SDimitry Andric Style.IntegerLiteralSeparator.Decimal = 3; 1933*0fca6ea1SDimitry Andric Style.IntegerLiteralSeparator.DecimalMinDigits = 5; 19345f757f3fSDimitry Andric Style.LineEnding = FormatStyle::LE_LF; 19355f757f3fSDimitry Andric Style.RemoveBracesLLVM = true; 19365f757f3fSDimitry Andric Style.RemoveParentheses = FormatStyle::RPS_ReturnStatement; 1937*0fca6ea1SDimitry Andric Style.RemoveSemicolon = true; 19385f757f3fSDimitry Andric return Style; 19395f757f3fSDimitry Andric } 19405f757f3fSDimitry Andric 19410b57cec5SDimitry Andric FormatStyle getNoStyle() { 19420b57cec5SDimitry Andric FormatStyle NoStyle = getLLVMStyle(); 19430b57cec5SDimitry Andric NoStyle.DisableFormat = true; 1944fe6060f1SDimitry Andric NoStyle.SortIncludes = FormatStyle::SI_Never; 1945bdd1243dSDimitry Andric NoStyle.SortUsingDeclarations = FormatStyle::SUD_Never; 19460b57cec5SDimitry Andric return NoStyle; 19470b57cec5SDimitry Andric } 19480b57cec5SDimitry Andric 19490b57cec5SDimitry Andric bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language, 19500b57cec5SDimitry Andric FormatStyle *Style) { 195181ad6265SDimitry Andric if (Name.equals_insensitive("llvm")) 19520b57cec5SDimitry Andric *Style = getLLVMStyle(Language); 195381ad6265SDimitry Andric else if (Name.equals_insensitive("chromium")) 19540b57cec5SDimitry Andric *Style = getChromiumStyle(Language); 195581ad6265SDimitry Andric else if (Name.equals_insensitive("mozilla")) 19560b57cec5SDimitry Andric *Style = getMozillaStyle(); 195781ad6265SDimitry Andric else if (Name.equals_insensitive("google")) 19580b57cec5SDimitry Andric *Style = getGoogleStyle(Language); 195981ad6265SDimitry Andric else if (Name.equals_insensitive("webkit")) 19600b57cec5SDimitry Andric *Style = getWebKitStyle(); 196181ad6265SDimitry Andric else if (Name.equals_insensitive("gnu")) 19620b57cec5SDimitry Andric *Style = getGNUStyle(); 196381ad6265SDimitry Andric else if (Name.equals_insensitive("microsoft")) 19640b57cec5SDimitry Andric *Style = getMicrosoftStyle(Language); 19655f757f3fSDimitry Andric else if (Name.equals_insensitive("clang-format")) 19665f757f3fSDimitry Andric *Style = getClangFormatStyle(); 196781ad6265SDimitry Andric else if (Name.equals_insensitive("none")) 19680b57cec5SDimitry Andric *Style = getNoStyle(); 196981ad6265SDimitry Andric else if (Name.equals_insensitive("inheritparentconfig")) 1970fe6060f1SDimitry Andric Style->InheritsParentConfig = true; 197181ad6265SDimitry Andric else 19720b57cec5SDimitry Andric return false; 19730b57cec5SDimitry Andric 19740b57cec5SDimitry Andric Style->Language = Language; 19750b57cec5SDimitry Andric return true; 19760b57cec5SDimitry Andric } 19770b57cec5SDimitry Andric 1978349cc55cSDimitry Andric ParseError validateQualifierOrder(FormatStyle *Style) { 1979349cc55cSDimitry Andric // If its empty then it means don't do anything. 1980349cc55cSDimitry Andric if (Style->QualifierOrder.empty()) 1981349cc55cSDimitry Andric return ParseError::MissingQualifierOrder; 1982349cc55cSDimitry Andric 1983349cc55cSDimitry Andric // Ensure the list contains only currently valid qualifiers. 1984349cc55cSDimitry Andric for (const auto &Qualifier : Style->QualifierOrder) { 1985349cc55cSDimitry Andric if (Qualifier == "type") 1986349cc55cSDimitry Andric continue; 1987349cc55cSDimitry Andric auto token = 1988349cc55cSDimitry Andric LeftRightQualifierAlignmentFixer::getTokenFromQualifier(Qualifier); 1989349cc55cSDimitry Andric if (token == tok::identifier) 1990349cc55cSDimitry Andric return ParseError::InvalidQualifierSpecified; 1991349cc55cSDimitry Andric } 199281ad6265SDimitry Andric 199381ad6265SDimitry Andric // Ensure the list is unique (no duplicates). 1994349cc55cSDimitry Andric std::set<std::string> UniqueQualifiers(Style->QualifierOrder.begin(), 1995349cc55cSDimitry Andric Style->QualifierOrder.end()); 1996349cc55cSDimitry Andric if (Style->QualifierOrder.size() != UniqueQualifiers.size()) { 1997349cc55cSDimitry Andric LLVM_DEBUG(llvm::dbgs() 1998349cc55cSDimitry Andric << "Duplicate Qualifiers " << Style->QualifierOrder.size() 1999349cc55cSDimitry Andric << " vs " << UniqueQualifiers.size() << "\n"); 2000349cc55cSDimitry Andric return ParseError::DuplicateQualifierSpecified; 2001349cc55cSDimitry Andric } 2002349cc55cSDimitry Andric 200381ad6265SDimitry Andric // Ensure the list has 'type' in it. 2004bdd1243dSDimitry Andric if (!llvm::is_contained(Style->QualifierOrder, "type")) 2005349cc55cSDimitry Andric return ParseError::MissingQualifierType; 200681ad6265SDimitry Andric 2007349cc55cSDimitry Andric return ParseError::Success; 2008349cc55cSDimitry Andric } 2009349cc55cSDimitry Andric 2010e8d8bef9SDimitry Andric std::error_code parseConfiguration(llvm::MemoryBufferRef Config, 2011fe6060f1SDimitry Andric FormatStyle *Style, bool AllowUnknownOptions, 2012fe6060f1SDimitry Andric llvm::SourceMgr::DiagHandlerTy DiagHandler, 2013fe6060f1SDimitry Andric void *DiagHandlerCtxt) { 20140b57cec5SDimitry Andric assert(Style); 20150b57cec5SDimitry Andric FormatStyle::LanguageKind Language = Style->Language; 20160b57cec5SDimitry Andric assert(Language != FormatStyle::LK_None); 2017e8d8bef9SDimitry Andric if (Config.getBuffer().trim().empty()) 201881ad6265SDimitry Andric return make_error_code(ParseError::Success); 20190b57cec5SDimitry Andric Style->StyleSet.Clear(); 20200b57cec5SDimitry Andric std::vector<FormatStyle> Styles; 2021fe6060f1SDimitry Andric llvm::yaml::Input Input(Config, /*Ctxt=*/nullptr, DiagHandler, 2022fe6060f1SDimitry Andric DiagHandlerCtxt); 20230b57cec5SDimitry Andric // DocumentListTraits<vector<FormatStyle>> uses the context to get default 20240b57cec5SDimitry Andric // values for the fields, keys for which are missing from the configuration. 20250b57cec5SDimitry Andric // Mapping also uses the context to get the language to find the correct 20260b57cec5SDimitry Andric // base style. 20270b57cec5SDimitry Andric Input.setContext(Style); 2028e8d8bef9SDimitry Andric Input.setAllowUnknownKeys(AllowUnknownOptions); 20290b57cec5SDimitry Andric Input >> Styles; 20300b57cec5SDimitry Andric if (Input.error()) 20310b57cec5SDimitry Andric return Input.error(); 20320b57cec5SDimitry Andric 20330b57cec5SDimitry Andric for (unsigned i = 0; i < Styles.size(); ++i) { 20340b57cec5SDimitry Andric // Ensures that only the first configuration can skip the Language option. 20350b57cec5SDimitry Andric if (Styles[i].Language == FormatStyle::LK_None && i != 0) 20360b57cec5SDimitry Andric return make_error_code(ParseError::Error); 20370b57cec5SDimitry Andric // Ensure that each language is configured at most once. 20380b57cec5SDimitry Andric for (unsigned j = 0; j < i; ++j) { 20390b57cec5SDimitry Andric if (Styles[i].Language == Styles[j].Language) { 20400b57cec5SDimitry Andric LLVM_DEBUG(llvm::dbgs() 20410b57cec5SDimitry Andric << "Duplicate languages in the config file on positions " 20420b57cec5SDimitry Andric << j << " and " << i << "\n"); 20430b57cec5SDimitry Andric return make_error_code(ParseError::Error); 20440b57cec5SDimitry Andric } 20450b57cec5SDimitry Andric } 20460b57cec5SDimitry Andric } 20470b57cec5SDimitry Andric // Look for a suitable configuration starting from the end, so we can 20480b57cec5SDimitry Andric // find the configuration for the specific language first, and the default 20490b57cec5SDimitry Andric // configuration (which can only be at slot 0) after it. 20500b57cec5SDimitry Andric FormatStyle::FormatStyleSet StyleSet; 20510b57cec5SDimitry Andric bool LanguageFound = false; 20521fd87a68SDimitry Andric for (const FormatStyle &Style : llvm::reverse(Styles)) { 20531fd87a68SDimitry Andric if (Style.Language != FormatStyle::LK_None) 20541fd87a68SDimitry Andric StyleSet.Add(Style); 20551fd87a68SDimitry Andric if (Style.Language == Language) 20560b57cec5SDimitry Andric LanguageFound = true; 20570b57cec5SDimitry Andric } 20580b57cec5SDimitry Andric if (!LanguageFound) { 20590b57cec5SDimitry Andric if (Styles.empty() || Styles[0].Language != FormatStyle::LK_None) 20600b57cec5SDimitry Andric return make_error_code(ParseError::Unsuitable); 20610b57cec5SDimitry Andric FormatStyle DefaultStyle = Styles[0]; 20620b57cec5SDimitry Andric DefaultStyle.Language = Language; 20630b57cec5SDimitry Andric StyleSet.Add(std::move(DefaultStyle)); 20640b57cec5SDimitry Andric } 20650b57cec5SDimitry Andric *Style = *StyleSet.Get(Language); 20665ffd83dbSDimitry Andric if (Style->InsertTrailingCommas != FormatStyle::TCS_None && 20675ffd83dbSDimitry Andric Style->BinPackArguments) { 20685ffd83dbSDimitry Andric // See comment on FormatStyle::TSC_Wrapped. 20695ffd83dbSDimitry Andric return make_error_code(ParseError::BinPackTrailingCommaConflict); 20705ffd83dbSDimitry Andric } 2071349cc55cSDimitry Andric if (Style->QualifierAlignment != FormatStyle::QAS_Leave) 2072349cc55cSDimitry Andric return make_error_code(validateQualifierOrder(Style)); 20730b57cec5SDimitry Andric return make_error_code(ParseError::Success); 20740b57cec5SDimitry Andric } 20750b57cec5SDimitry Andric 20760b57cec5SDimitry Andric std::string configurationAsText(const FormatStyle &Style) { 20770b57cec5SDimitry Andric std::string Text; 20780b57cec5SDimitry Andric llvm::raw_string_ostream Stream(Text); 20790b57cec5SDimitry Andric llvm::yaml::Output Output(Stream); 20800b57cec5SDimitry Andric // We use the same mapping method for input and output, so we need a non-const 20810b57cec5SDimitry Andric // reference here. 2082349cc55cSDimitry Andric FormatStyle NonConstStyle = Style; 2083349cc55cSDimitry Andric expandPresetsBraceWrapping(NonConstStyle); 2084349cc55cSDimitry Andric expandPresetsSpaceBeforeParens(NonConstStyle); 208506c3fb27SDimitry Andric expandPresetsSpacesInParens(NonConstStyle); 20860b57cec5SDimitry Andric Output << NonConstStyle; 2087349cc55cSDimitry Andric 20880b57cec5SDimitry Andric return Stream.str(); 20890b57cec5SDimitry Andric } 20900b57cec5SDimitry Andric 2091bdd1243dSDimitry Andric std::optional<FormatStyle> 20920b57cec5SDimitry Andric FormatStyle::FormatStyleSet::Get(FormatStyle::LanguageKind Language) const { 20930b57cec5SDimitry Andric if (!Styles) 2094bdd1243dSDimitry Andric return std::nullopt; 20950b57cec5SDimitry Andric auto It = Styles->find(Language); 20960b57cec5SDimitry Andric if (It == Styles->end()) 2097bdd1243dSDimitry Andric return std::nullopt; 20980b57cec5SDimitry Andric FormatStyle Style = It->second; 20990b57cec5SDimitry Andric Style.StyleSet = *this; 21000b57cec5SDimitry Andric return Style; 21010b57cec5SDimitry Andric } 21020b57cec5SDimitry Andric 21030b57cec5SDimitry Andric void FormatStyle::FormatStyleSet::Add(FormatStyle Style) { 21040b57cec5SDimitry Andric assert(Style.Language != LK_None && 21050b57cec5SDimitry Andric "Cannot add a style for LK_None to a StyleSet"); 21060b57cec5SDimitry Andric assert( 21070b57cec5SDimitry Andric !Style.StyleSet.Styles && 21080b57cec5SDimitry Andric "Cannot add a style associated with an existing StyleSet to a StyleSet"); 21090b57cec5SDimitry Andric if (!Styles) 21100b57cec5SDimitry Andric Styles = std::make_shared<MapType>(); 21110b57cec5SDimitry Andric (*Styles)[Style.Language] = std::move(Style); 21120b57cec5SDimitry Andric } 21130b57cec5SDimitry Andric 21140b57cec5SDimitry Andric void FormatStyle::FormatStyleSet::Clear() { Styles.reset(); } 21150b57cec5SDimitry Andric 2116bdd1243dSDimitry Andric std::optional<FormatStyle> 21170b57cec5SDimitry Andric FormatStyle::GetLanguageStyle(FormatStyle::LanguageKind Language) const { 21180b57cec5SDimitry Andric return StyleSet.Get(Language); 21190b57cec5SDimitry Andric } 21200b57cec5SDimitry Andric 21210b57cec5SDimitry Andric namespace { 21220b57cec5SDimitry Andric 212306c3fb27SDimitry Andric class ParensRemover : public TokenAnalyzer { 212406c3fb27SDimitry Andric public: 212506c3fb27SDimitry Andric ParensRemover(const Environment &Env, const FormatStyle &Style) 212606c3fb27SDimitry Andric : TokenAnalyzer(Env, Style) {} 212706c3fb27SDimitry Andric 212806c3fb27SDimitry Andric std::pair<tooling::Replacements, unsigned> 212906c3fb27SDimitry Andric analyze(TokenAnnotator &Annotator, 213006c3fb27SDimitry Andric SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 213106c3fb27SDimitry Andric FormatTokenLexer &Tokens) override { 213206c3fb27SDimitry Andric AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 213306c3fb27SDimitry Andric tooling::Replacements Result; 213406c3fb27SDimitry Andric removeParens(AnnotatedLines, Result); 213506c3fb27SDimitry Andric return {Result, 0}; 213606c3fb27SDimitry Andric } 213706c3fb27SDimitry Andric 213806c3fb27SDimitry Andric private: 213906c3fb27SDimitry Andric void removeParens(SmallVectorImpl<AnnotatedLine *> &Lines, 214006c3fb27SDimitry Andric tooling::Replacements &Result) { 214106c3fb27SDimitry Andric const auto &SourceMgr = Env.getSourceManager(); 214206c3fb27SDimitry Andric for (auto *Line : Lines) { 214306c3fb27SDimitry Andric removeParens(Line->Children, Result); 214406c3fb27SDimitry Andric if (!Line->Affected) 214506c3fb27SDimitry Andric continue; 214606c3fb27SDimitry Andric for (const auto *Token = Line->First; Token && !Token->Finalized; 214706c3fb27SDimitry Andric Token = Token->Next) { 214806c3fb27SDimitry Andric if (!Token->Optional || !Token->isOneOf(tok::l_paren, tok::r_paren)) 214906c3fb27SDimitry Andric continue; 215006c3fb27SDimitry Andric auto *Next = Token->Next; 215106c3fb27SDimitry Andric assert(Next && Next->isNot(tok::eof)); 215206c3fb27SDimitry Andric SourceLocation Start; 215306c3fb27SDimitry Andric if (Next->NewlinesBefore == 0) { 215406c3fb27SDimitry Andric Start = Token->Tok.getLocation(); 215506c3fb27SDimitry Andric Next->WhitespaceRange = Token->WhitespaceRange; 215606c3fb27SDimitry Andric } else { 215706c3fb27SDimitry Andric Start = Token->WhitespaceRange.getBegin(); 215806c3fb27SDimitry Andric } 215906c3fb27SDimitry Andric const auto &Range = 216006c3fb27SDimitry Andric CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc()); 216106c3fb27SDimitry Andric cantFail(Result.add(tooling::Replacement(SourceMgr, Range, " "))); 216206c3fb27SDimitry Andric } 216306c3fb27SDimitry Andric } 216406c3fb27SDimitry Andric } 216506c3fb27SDimitry Andric }; 216606c3fb27SDimitry Andric 216781ad6265SDimitry Andric class BracesInserter : public TokenAnalyzer { 216881ad6265SDimitry Andric public: 216981ad6265SDimitry Andric BracesInserter(const Environment &Env, const FormatStyle &Style) 2170bdd1243dSDimitry Andric : TokenAnalyzer(Env, Style) {} 217181ad6265SDimitry Andric 217281ad6265SDimitry Andric std::pair<tooling::Replacements, unsigned> 217381ad6265SDimitry Andric analyze(TokenAnnotator &Annotator, 217481ad6265SDimitry Andric SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 217581ad6265SDimitry Andric FormatTokenLexer &Tokens) override { 217681ad6265SDimitry Andric AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 217781ad6265SDimitry Andric tooling::Replacements Result; 217881ad6265SDimitry Andric insertBraces(AnnotatedLines, Result); 217981ad6265SDimitry Andric return {Result, 0}; 218081ad6265SDimitry Andric } 218181ad6265SDimitry Andric 218281ad6265SDimitry Andric private: 218381ad6265SDimitry Andric void insertBraces(SmallVectorImpl<AnnotatedLine *> &Lines, 218481ad6265SDimitry Andric tooling::Replacements &Result) { 218581ad6265SDimitry Andric const auto &SourceMgr = Env.getSourceManager(); 2186bdd1243dSDimitry Andric int OpeningBraceSurplus = 0; 218781ad6265SDimitry Andric for (AnnotatedLine *Line : Lines) { 218881ad6265SDimitry Andric insertBraces(Line->Children, Result); 2189bdd1243dSDimitry Andric if (!Line->Affected && OpeningBraceSurplus == 0) 219081ad6265SDimitry Andric continue; 219181ad6265SDimitry Andric for (FormatToken *Token = Line->First; Token && !Token->Finalized; 219281ad6265SDimitry Andric Token = Token->Next) { 2193bdd1243dSDimitry Andric int BraceCount = Token->BraceCount; 2194bdd1243dSDimitry Andric if (BraceCount == 0) 219581ad6265SDimitry Andric continue; 219681ad6265SDimitry Andric std::string Brace; 2197bdd1243dSDimitry Andric if (BraceCount < 0) { 2198bdd1243dSDimitry Andric assert(BraceCount == -1); 2199bdd1243dSDimitry Andric if (!Line->Affected) 2200bdd1243dSDimitry Andric break; 2201bdd1243dSDimitry Andric Brace = Token->is(tok::comment) ? "\n{" : "{"; 2202bdd1243dSDimitry Andric ++OpeningBraceSurplus; 220381ad6265SDimitry Andric } else { 2204bdd1243dSDimitry Andric if (OpeningBraceSurplus == 0) 2205bdd1243dSDimitry Andric break; 2206bdd1243dSDimitry Andric if (OpeningBraceSurplus < BraceCount) 2207bdd1243dSDimitry Andric BraceCount = OpeningBraceSurplus; 2208bdd1243dSDimitry Andric Brace = '\n' + std::string(BraceCount, '}'); 2209bdd1243dSDimitry Andric OpeningBraceSurplus -= BraceCount; 221081ad6265SDimitry Andric } 221181ad6265SDimitry Andric Token->BraceCount = 0; 221281ad6265SDimitry Andric const auto Start = Token->Tok.getEndLoc(); 221381ad6265SDimitry Andric cantFail(Result.add(tooling::Replacement(SourceMgr, Start, 0, Brace))); 221481ad6265SDimitry Andric } 221581ad6265SDimitry Andric } 2216bdd1243dSDimitry Andric assert(OpeningBraceSurplus == 0); 221781ad6265SDimitry Andric } 221881ad6265SDimitry Andric }; 221981ad6265SDimitry Andric 222004eeddc0SDimitry Andric class BracesRemover : public TokenAnalyzer { 222104eeddc0SDimitry Andric public: 222204eeddc0SDimitry Andric BracesRemover(const Environment &Env, const FormatStyle &Style) 2223bdd1243dSDimitry Andric : TokenAnalyzer(Env, Style) {} 222404eeddc0SDimitry Andric 222504eeddc0SDimitry Andric std::pair<tooling::Replacements, unsigned> 222604eeddc0SDimitry Andric analyze(TokenAnnotator &Annotator, 222704eeddc0SDimitry Andric SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 222804eeddc0SDimitry Andric FormatTokenLexer &Tokens) override { 222904eeddc0SDimitry Andric AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 223004eeddc0SDimitry Andric tooling::Replacements Result; 223104eeddc0SDimitry Andric removeBraces(AnnotatedLines, Result); 223204eeddc0SDimitry Andric return {Result, 0}; 223304eeddc0SDimitry Andric } 223404eeddc0SDimitry Andric 223504eeddc0SDimitry Andric private: 223604eeddc0SDimitry Andric void removeBraces(SmallVectorImpl<AnnotatedLine *> &Lines, 223704eeddc0SDimitry Andric tooling::Replacements &Result) { 223804eeddc0SDimitry Andric const auto &SourceMgr = Env.getSourceManager(); 2239bdd1243dSDimitry Andric const auto End = Lines.end(); 2240bdd1243dSDimitry Andric for (auto I = Lines.begin(); I != End; ++I) { 2241bdd1243dSDimitry Andric const auto Line = *I; 224204eeddc0SDimitry Andric removeBraces(Line->Children, Result); 2243bdd1243dSDimitry Andric if (!Line->Affected) 2244bdd1243dSDimitry Andric continue; 2245bdd1243dSDimitry Andric const auto NextLine = I + 1 == End ? nullptr : I[1]; 2246bdd1243dSDimitry Andric for (auto Token = Line->First; Token && !Token->Finalized; 224781ad6265SDimitry Andric Token = Token->Next) { 224804eeddc0SDimitry Andric if (!Token->Optional) 224904eeddc0SDimitry Andric continue; 2250bdd1243dSDimitry Andric if (!Token->isOneOf(tok::l_brace, tok::r_brace)) 2251bdd1243dSDimitry Andric continue; 2252bdd1243dSDimitry Andric auto Next = Token->Next; 2253fcaf7f86SDimitry Andric assert(Next || Token == Line->Last); 2254bdd1243dSDimitry Andric if (!Next && NextLine) 2255bdd1243dSDimitry Andric Next = NextLine->First; 2256bdd1243dSDimitry Andric SourceLocation Start; 2257bdd1243dSDimitry Andric if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) { 2258bdd1243dSDimitry Andric Start = Token->Tok.getLocation(); 2259bdd1243dSDimitry Andric Next->WhitespaceRange = Token->WhitespaceRange; 2260bdd1243dSDimitry Andric } else { 2261bdd1243dSDimitry Andric Start = Token->WhitespaceRange.getBegin(); 2262bdd1243dSDimitry Andric } 226304eeddc0SDimitry Andric const auto Range = 226404eeddc0SDimitry Andric CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc()); 226504eeddc0SDimitry Andric cantFail(Result.add(tooling::Replacement(SourceMgr, Range, ""))); 226604eeddc0SDimitry Andric } 226704eeddc0SDimitry Andric } 2268bdd1243dSDimitry Andric } 2269bdd1243dSDimitry Andric }; 2270bdd1243dSDimitry Andric 2271bdd1243dSDimitry Andric class SemiRemover : public TokenAnalyzer { 2272bdd1243dSDimitry Andric public: 2273bdd1243dSDimitry Andric SemiRemover(const Environment &Env, const FormatStyle &Style) 2274bdd1243dSDimitry Andric : TokenAnalyzer(Env, Style) {} 2275bdd1243dSDimitry Andric 2276bdd1243dSDimitry Andric std::pair<tooling::Replacements, unsigned> 2277bdd1243dSDimitry Andric analyze(TokenAnnotator &Annotator, 2278bdd1243dSDimitry Andric SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2279bdd1243dSDimitry Andric FormatTokenLexer &Tokens) override { 2280bdd1243dSDimitry Andric AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 2281bdd1243dSDimitry Andric tooling::Replacements Result; 2282*0fca6ea1SDimitry Andric removeSemi(Annotator, AnnotatedLines, Result); 2283bdd1243dSDimitry Andric return {Result, 0}; 2284bdd1243dSDimitry Andric } 2285bdd1243dSDimitry Andric 2286bdd1243dSDimitry Andric private: 2287*0fca6ea1SDimitry Andric void removeSemi(TokenAnnotator &Annotator, 2288*0fca6ea1SDimitry Andric SmallVectorImpl<AnnotatedLine *> &Lines, 2289bdd1243dSDimitry Andric tooling::Replacements &Result) { 2290*0fca6ea1SDimitry Andric auto PrecededByFunctionRBrace = [](const FormatToken &Tok) { 2291*0fca6ea1SDimitry Andric const auto *Prev = Tok.Previous; 2292*0fca6ea1SDimitry Andric if (!Prev || Prev->isNot(tok::r_brace)) 2293*0fca6ea1SDimitry Andric return false; 2294*0fca6ea1SDimitry Andric const auto *LBrace = Prev->MatchingParen; 2295*0fca6ea1SDimitry Andric return LBrace && LBrace->is(TT_FunctionLBrace); 2296*0fca6ea1SDimitry Andric }; 2297bdd1243dSDimitry Andric const auto &SourceMgr = Env.getSourceManager(); 2298bdd1243dSDimitry Andric const auto End = Lines.end(); 2299bdd1243dSDimitry Andric for (auto I = Lines.begin(); I != End; ++I) { 2300bdd1243dSDimitry Andric const auto Line = *I; 2301*0fca6ea1SDimitry Andric removeSemi(Annotator, Line->Children, Result); 2302bdd1243dSDimitry Andric if (!Line->Affected) 2303bdd1243dSDimitry Andric continue; 2304*0fca6ea1SDimitry Andric Annotator.calculateFormattingInformation(*Line); 2305bdd1243dSDimitry Andric const auto NextLine = I + 1 == End ? nullptr : I[1]; 2306bdd1243dSDimitry Andric for (auto Token = Line->First; Token && !Token->Finalized; 2307bdd1243dSDimitry Andric Token = Token->Next) { 2308*0fca6ea1SDimitry Andric if (Token->isNot(tok::semi) || 2309*0fca6ea1SDimitry Andric (!Token->Optional && !PrecededByFunctionRBrace(*Token))) { 2310bdd1243dSDimitry Andric continue; 2311*0fca6ea1SDimitry Andric } 2312bdd1243dSDimitry Andric auto Next = Token->Next; 2313bdd1243dSDimitry Andric assert(Next || Token == Line->Last); 2314bdd1243dSDimitry Andric if (!Next && NextLine) 2315bdd1243dSDimitry Andric Next = NextLine->First; 2316bdd1243dSDimitry Andric SourceLocation Start; 2317bdd1243dSDimitry Andric if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) { 2318bdd1243dSDimitry Andric Start = Token->Tok.getLocation(); 2319bdd1243dSDimitry Andric Next->WhitespaceRange = Token->WhitespaceRange; 2320bdd1243dSDimitry Andric } else { 2321bdd1243dSDimitry Andric Start = Token->WhitespaceRange.getBegin(); 2322bdd1243dSDimitry Andric } 2323bdd1243dSDimitry Andric const auto Range = 2324bdd1243dSDimitry Andric CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc()); 2325bdd1243dSDimitry Andric cantFail(Result.add(tooling::Replacement(SourceMgr, Range, ""))); 2326bdd1243dSDimitry Andric } 2327fcaf7f86SDimitry Andric } 232804eeddc0SDimitry Andric } 232904eeddc0SDimitry Andric }; 233004eeddc0SDimitry Andric 23310b57cec5SDimitry Andric class JavaScriptRequoter : public TokenAnalyzer { 23320b57cec5SDimitry Andric public: 23330b57cec5SDimitry Andric JavaScriptRequoter(const Environment &Env, const FormatStyle &Style) 23340b57cec5SDimitry Andric : TokenAnalyzer(Env, Style) {} 23350b57cec5SDimitry Andric 23360b57cec5SDimitry Andric std::pair<tooling::Replacements, unsigned> 23370b57cec5SDimitry Andric analyze(TokenAnnotator &Annotator, 23380b57cec5SDimitry Andric SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 23390b57cec5SDimitry Andric FormatTokenLexer &Tokens) override { 23400b57cec5SDimitry Andric AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 23410b57cec5SDimitry Andric tooling::Replacements Result; 23420b57cec5SDimitry Andric requoteJSStringLiteral(AnnotatedLines, Result); 23430b57cec5SDimitry Andric return {Result, 0}; 23440b57cec5SDimitry Andric } 23450b57cec5SDimitry Andric 23460b57cec5SDimitry Andric private: 23470b57cec5SDimitry Andric // Replaces double/single-quoted string literal as appropriate, re-escaping 23480b57cec5SDimitry Andric // the contents in the process. 23490b57cec5SDimitry Andric void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines, 23500b57cec5SDimitry Andric tooling::Replacements &Result) { 23510b57cec5SDimitry Andric for (AnnotatedLine *Line : Lines) { 23520b57cec5SDimitry Andric requoteJSStringLiteral(Line->Children, Result); 23530b57cec5SDimitry Andric if (!Line->Affected) 23540b57cec5SDimitry Andric continue; 23550b57cec5SDimitry Andric for (FormatToken *FormatTok = Line->First; FormatTok; 23560b57cec5SDimitry Andric FormatTok = FormatTok->Next) { 23570b57cec5SDimitry Andric StringRef Input = FormatTok->TokenText; 23580b57cec5SDimitry Andric if (FormatTok->Finalized || !FormatTok->isStringLiteral() || 23590b57cec5SDimitry Andric // NB: testing for not starting with a double quote to avoid 23600b57cec5SDimitry Andric // breaking `template strings`. 23610b57cec5SDimitry Andric (Style.JavaScriptQuotes == FormatStyle::JSQS_Single && 23625f757f3fSDimitry Andric !Input.starts_with("\"")) || 23630b57cec5SDimitry Andric (Style.JavaScriptQuotes == FormatStyle::JSQS_Double && 23645f757f3fSDimitry Andric !Input.starts_with("\'"))) { 23650b57cec5SDimitry Andric continue; 236681ad6265SDimitry Andric } 23670b57cec5SDimitry Andric 23680b57cec5SDimitry Andric // Change start and end quote. 23690b57cec5SDimitry Andric bool IsSingle = Style.JavaScriptQuotes == FormatStyle::JSQS_Single; 23700b57cec5SDimitry Andric SourceLocation Start = FormatTok->Tok.getLocation(); 23710b57cec5SDimitry Andric auto Replace = [&](SourceLocation Start, unsigned Length, 23720b57cec5SDimitry Andric StringRef ReplacementText) { 23730b57cec5SDimitry Andric auto Err = Result.add(tooling::Replacement( 23740b57cec5SDimitry Andric Env.getSourceManager(), Start, Length, ReplacementText)); 23750b57cec5SDimitry Andric // FIXME: handle error. For now, print error message and skip the 23760b57cec5SDimitry Andric // replacement for release version. 23770b57cec5SDimitry Andric if (Err) { 2378*0fca6ea1SDimitry Andric llvm::errs() << toString(std::move(Err)) << "\n"; 23790b57cec5SDimitry Andric assert(false); 23800b57cec5SDimitry Andric } 23810b57cec5SDimitry Andric }; 23820b57cec5SDimitry Andric Replace(Start, 1, IsSingle ? "'" : "\""); 23830b57cec5SDimitry Andric Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1, 23840b57cec5SDimitry Andric IsSingle ? "'" : "\""); 23850b57cec5SDimitry Andric 23860b57cec5SDimitry Andric // Escape internal quotes. 23870b57cec5SDimitry Andric bool Escaped = false; 23880b57cec5SDimitry Andric for (size_t i = 1; i < Input.size() - 1; i++) { 23890b57cec5SDimitry Andric switch (Input[i]) { 23900b57cec5SDimitry Andric case '\\': 23910b57cec5SDimitry Andric if (!Escaped && i + 1 < Input.size() && 23920b57cec5SDimitry Andric ((IsSingle && Input[i + 1] == '"') || 23930b57cec5SDimitry Andric (!IsSingle && Input[i + 1] == '\''))) { 23940b57cec5SDimitry Andric // Remove this \, it's escaping a " or ' that no longer needs 23950b57cec5SDimitry Andric // escaping 23960b57cec5SDimitry Andric Replace(Start.getLocWithOffset(i), 1, ""); 23970b57cec5SDimitry Andric continue; 23980b57cec5SDimitry Andric } 23990b57cec5SDimitry Andric Escaped = !Escaped; 24000b57cec5SDimitry Andric break; 24010b57cec5SDimitry Andric case '\"': 24020b57cec5SDimitry Andric case '\'': 24030b57cec5SDimitry Andric if (!Escaped && IsSingle == (Input[i] == '\'')) { 24040b57cec5SDimitry Andric // Escape the quote. 24050b57cec5SDimitry Andric Replace(Start.getLocWithOffset(i), 0, "\\"); 24060b57cec5SDimitry Andric } 24070b57cec5SDimitry Andric Escaped = false; 24080b57cec5SDimitry Andric break; 24090b57cec5SDimitry Andric default: 24100b57cec5SDimitry Andric Escaped = false; 24110b57cec5SDimitry Andric break; 24120b57cec5SDimitry Andric } 24130b57cec5SDimitry Andric } 24140b57cec5SDimitry Andric } 24150b57cec5SDimitry Andric } 24160b57cec5SDimitry Andric } 24170b57cec5SDimitry Andric }; 24180b57cec5SDimitry Andric 24190b57cec5SDimitry Andric class Formatter : public TokenAnalyzer { 24200b57cec5SDimitry Andric public: 24210b57cec5SDimitry Andric Formatter(const Environment &Env, const FormatStyle &Style, 24220b57cec5SDimitry Andric FormattingAttemptStatus *Status) 24230b57cec5SDimitry Andric : TokenAnalyzer(Env, Style), Status(Status) {} 24240b57cec5SDimitry Andric 24250b57cec5SDimitry Andric std::pair<tooling::Replacements, unsigned> 24260b57cec5SDimitry Andric analyze(TokenAnnotator &Annotator, 24270b57cec5SDimitry Andric SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 24280b57cec5SDimitry Andric FormatTokenLexer &Tokens) override { 24290b57cec5SDimitry Andric tooling::Replacements Result; 24300b57cec5SDimitry Andric deriveLocalStyle(AnnotatedLines); 24310b57cec5SDimitry Andric AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 24321fd87a68SDimitry Andric for (AnnotatedLine *Line : AnnotatedLines) 24331fd87a68SDimitry Andric Annotator.calculateFormattingInformation(*Line); 24340b57cec5SDimitry Andric Annotator.setCommentLineLevels(AnnotatedLines); 24350b57cec5SDimitry Andric 24360b57cec5SDimitry Andric WhitespaceManager Whitespaces( 24370b57cec5SDimitry Andric Env.getSourceManager(), Style, 2438bdd1243dSDimitry Andric Style.LineEnding > FormatStyle::LE_CRLF 243904eeddc0SDimitry Andric ? WhitespaceManager::inputUsesCRLF( 2440480093f4SDimitry Andric Env.getSourceManager().getBufferData(Env.getFileID()), 2441bdd1243dSDimitry Andric Style.LineEnding == FormatStyle::LE_DeriveCRLF) 2442bdd1243dSDimitry Andric : Style.LineEnding == FormatStyle::LE_CRLF); 24430b57cec5SDimitry Andric ContinuationIndenter Indenter(Style, Tokens.getKeywords(), 24440b57cec5SDimitry Andric Env.getSourceManager(), Whitespaces, Encoding, 24450b57cec5SDimitry Andric BinPackInconclusiveFunctions); 24460b57cec5SDimitry Andric unsigned Penalty = 24470b57cec5SDimitry Andric UnwrappedLineFormatter(&Indenter, &Whitespaces, Style, 24480b57cec5SDimitry Andric Tokens.getKeywords(), Env.getSourceManager(), 24490b57cec5SDimitry Andric Status) 24500b57cec5SDimitry Andric .format(AnnotatedLines, /*DryRun=*/false, 24510b57cec5SDimitry Andric /*AdditionalIndent=*/0, 24520b57cec5SDimitry Andric /*FixBadIndentation=*/false, 24530b57cec5SDimitry Andric /*FirstStartColumn=*/Env.getFirstStartColumn(), 24540b57cec5SDimitry Andric /*NextStartColumn=*/Env.getNextStartColumn(), 24550b57cec5SDimitry Andric /*LastStartColumn=*/Env.getLastStartColumn()); 24560b57cec5SDimitry Andric for (const auto &R : Whitespaces.generateReplacements()) 24570b57cec5SDimitry Andric if (Result.add(R)) 24580b57cec5SDimitry Andric return std::make_pair(Result, 0); 24590b57cec5SDimitry Andric return std::make_pair(Result, Penalty); 24600b57cec5SDimitry Andric } 24610b57cec5SDimitry Andric 24620b57cec5SDimitry Andric private: 24630b57cec5SDimitry Andric bool 24640b57cec5SDimitry Andric hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine *> &Lines) { 24650b57cec5SDimitry Andric for (const AnnotatedLine *Line : Lines) { 24660b57cec5SDimitry Andric if (hasCpp03IncompatibleFormat(Line->Children)) 24670b57cec5SDimitry Andric return true; 24680b57cec5SDimitry Andric for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) { 246904eeddc0SDimitry Andric if (!Tok->hasWhitespaceBefore()) { 24700b57cec5SDimitry Andric if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener)) 24710b57cec5SDimitry Andric return true; 24720b57cec5SDimitry Andric if (Tok->is(TT_TemplateCloser) && 247381ad6265SDimitry Andric Tok->Previous->is(TT_TemplateCloser)) { 24740b57cec5SDimitry Andric return true; 24750b57cec5SDimitry Andric } 24760b57cec5SDimitry Andric } 24770b57cec5SDimitry Andric } 247881ad6265SDimitry Andric } 24790b57cec5SDimitry Andric return false; 24800b57cec5SDimitry Andric } 24810b57cec5SDimitry Andric 24820b57cec5SDimitry Andric int countVariableAlignments(const SmallVectorImpl<AnnotatedLine *> &Lines) { 24830b57cec5SDimitry Andric int AlignmentDiff = 0; 24840b57cec5SDimitry Andric for (const AnnotatedLine *Line : Lines) { 24850b57cec5SDimitry Andric AlignmentDiff += countVariableAlignments(Line->Children); 24860b57cec5SDimitry Andric for (FormatToken *Tok = Line->First; Tok && Tok->Next; Tok = Tok->Next) { 24875f757f3fSDimitry Andric if (Tok->isNot(TT_PointerOrReference)) 24880b57cec5SDimitry Andric continue; 248981ad6265SDimitry Andric // Don't treat space in `void foo() &&` as evidence. 249081ad6265SDimitry Andric if (const auto *Prev = Tok->getPreviousNonComment()) { 249181ad6265SDimitry Andric if (Prev->is(tok::r_paren) && Prev->MatchingParen) { 249281ad6265SDimitry Andric if (const auto *Func = 249381ad6265SDimitry Andric Prev->MatchingParen->getPreviousNonComment()) { 249481ad6265SDimitry Andric if (Func->isOneOf(TT_FunctionDeclarationName, TT_StartOfName, 249581ad6265SDimitry Andric TT_OverloadedOperator)) { 249681ad6265SDimitry Andric continue; 249781ad6265SDimitry Andric } 249881ad6265SDimitry Andric } 249981ad6265SDimitry Andric } 250081ad6265SDimitry Andric } 250104eeddc0SDimitry Andric bool SpaceBefore = Tok->hasWhitespaceBefore(); 250204eeddc0SDimitry Andric bool SpaceAfter = Tok->Next->hasWhitespaceBefore(); 25030b57cec5SDimitry Andric if (SpaceBefore && !SpaceAfter) 25040b57cec5SDimitry Andric ++AlignmentDiff; 25050b57cec5SDimitry Andric if (!SpaceBefore && SpaceAfter) 25060b57cec5SDimitry Andric --AlignmentDiff; 25070b57cec5SDimitry Andric } 25080b57cec5SDimitry Andric } 25090b57cec5SDimitry Andric return AlignmentDiff; 25100b57cec5SDimitry Andric } 25110b57cec5SDimitry Andric 25120b57cec5SDimitry Andric void 25130b57cec5SDimitry Andric deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { 25140b57cec5SDimitry Andric bool HasBinPackedFunction = false; 25150b57cec5SDimitry Andric bool HasOnePerLineFunction = false; 25161fd87a68SDimitry Andric for (AnnotatedLine *Line : AnnotatedLines) { 25171fd87a68SDimitry Andric if (!Line->First->Next) 25180b57cec5SDimitry Andric continue; 25191fd87a68SDimitry Andric FormatToken *Tok = Line->First->Next; 25200b57cec5SDimitry Andric while (Tok->Next) { 2521e8d8bef9SDimitry Andric if (Tok->is(PPK_BinPacked)) 25220b57cec5SDimitry Andric HasBinPackedFunction = true; 2523e8d8bef9SDimitry Andric if (Tok->is(PPK_OnePerLine)) 25240b57cec5SDimitry Andric HasOnePerLineFunction = true; 25250b57cec5SDimitry Andric 25260b57cec5SDimitry Andric Tok = Tok->Next; 25270b57cec5SDimitry Andric } 25280b57cec5SDimitry Andric } 2529fe6060f1SDimitry Andric if (Style.DerivePointerAlignment) { 2530bdd1243dSDimitry Andric const auto NetRightCount = countVariableAlignments(AnnotatedLines); 2531bdd1243dSDimitry Andric if (NetRightCount > 0) 2532bdd1243dSDimitry Andric Style.PointerAlignment = FormatStyle::PAS_Right; 2533bdd1243dSDimitry Andric else if (NetRightCount < 0) 2534bdd1243dSDimitry Andric Style.PointerAlignment = FormatStyle::PAS_Left; 2535fe6060f1SDimitry Andric Style.ReferenceAlignment = FormatStyle::RAS_Pointer; 2536fe6060f1SDimitry Andric } 253781ad6265SDimitry Andric if (Style.Standard == FormatStyle::LS_Auto) { 25380b57cec5SDimitry Andric Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines) 2539a7dea167SDimitry Andric ? FormatStyle::LS_Latest 25400b57cec5SDimitry Andric : FormatStyle::LS_Cpp03; 254181ad6265SDimitry Andric } 25420b57cec5SDimitry Andric BinPackInconclusiveFunctions = 25430b57cec5SDimitry Andric HasBinPackedFunction || !HasOnePerLineFunction; 25440b57cec5SDimitry Andric } 25450b57cec5SDimitry Andric 25460b57cec5SDimitry Andric bool BinPackInconclusiveFunctions; 25470b57cec5SDimitry Andric FormattingAttemptStatus *Status; 25480b57cec5SDimitry Andric }; 25490b57cec5SDimitry Andric 25505ffd83dbSDimitry Andric /// TrailingCommaInserter inserts trailing commas into container literals. 25515ffd83dbSDimitry Andric /// E.g.: 25525ffd83dbSDimitry Andric /// const x = [ 25535ffd83dbSDimitry Andric /// 1, 25545ffd83dbSDimitry Andric /// ]; 25555ffd83dbSDimitry Andric /// TrailingCommaInserter runs after formatting. To avoid causing a required 25565ffd83dbSDimitry Andric /// reformatting (and thus reflow), it never inserts a comma that'd exceed the 25575ffd83dbSDimitry Andric /// ColumnLimit. 25585ffd83dbSDimitry Andric /// 25595ffd83dbSDimitry Andric /// Because trailing commas disable binpacking of arrays, TrailingCommaInserter 25605ffd83dbSDimitry Andric /// is conceptually incompatible with bin packing. 25615ffd83dbSDimitry Andric class TrailingCommaInserter : public TokenAnalyzer { 25625ffd83dbSDimitry Andric public: 25635ffd83dbSDimitry Andric TrailingCommaInserter(const Environment &Env, const FormatStyle &Style) 25645ffd83dbSDimitry Andric : TokenAnalyzer(Env, Style) {} 25655ffd83dbSDimitry Andric 25665ffd83dbSDimitry Andric std::pair<tooling::Replacements, unsigned> 25675ffd83dbSDimitry Andric analyze(TokenAnnotator &Annotator, 25685ffd83dbSDimitry Andric SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 25695ffd83dbSDimitry Andric FormatTokenLexer &Tokens) override { 25705ffd83dbSDimitry Andric AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 25715ffd83dbSDimitry Andric tooling::Replacements Result; 25725ffd83dbSDimitry Andric insertTrailingCommas(AnnotatedLines, Result); 25735ffd83dbSDimitry Andric return {Result, 0}; 25745ffd83dbSDimitry Andric } 25755ffd83dbSDimitry Andric 25765ffd83dbSDimitry Andric private: 25775ffd83dbSDimitry Andric /// Inserts trailing commas in [] and {} initializers if they wrap over 25785ffd83dbSDimitry Andric /// multiple lines. 25795ffd83dbSDimitry Andric void insertTrailingCommas(SmallVectorImpl<AnnotatedLine *> &Lines, 25805ffd83dbSDimitry Andric tooling::Replacements &Result) { 25815ffd83dbSDimitry Andric for (AnnotatedLine *Line : Lines) { 25825ffd83dbSDimitry Andric insertTrailingCommas(Line->Children, Result); 25835ffd83dbSDimitry Andric if (!Line->Affected) 25845ffd83dbSDimitry Andric continue; 25855ffd83dbSDimitry Andric for (FormatToken *FormatTok = Line->First; FormatTok; 25865ffd83dbSDimitry Andric FormatTok = FormatTok->Next) { 25875ffd83dbSDimitry Andric if (FormatTok->NewlinesBefore == 0) 25885ffd83dbSDimitry Andric continue; 25895ffd83dbSDimitry Andric FormatToken *Matching = FormatTok->MatchingParen; 25905ffd83dbSDimitry Andric if (!Matching || !FormatTok->getPreviousNonComment()) 25915ffd83dbSDimitry Andric continue; 25925ffd83dbSDimitry Andric if (!(FormatTok->is(tok::r_square) && 25935ffd83dbSDimitry Andric Matching->is(TT_ArrayInitializerLSquare)) && 259481ad6265SDimitry Andric !(FormatTok->is(tok::r_brace) && Matching->is(TT_DictLiteral))) { 25955ffd83dbSDimitry Andric continue; 259681ad6265SDimitry Andric } 25975ffd83dbSDimitry Andric FormatToken *Prev = FormatTok->getPreviousNonComment(); 25985ffd83dbSDimitry Andric if (Prev->is(tok::comma) || Prev->is(tok::semi)) 25995ffd83dbSDimitry Andric continue; 26005ffd83dbSDimitry Andric // getEndLoc is not reliably set during re-lexing, use text length 26015ffd83dbSDimitry Andric // instead. 26025ffd83dbSDimitry Andric SourceLocation Start = 26035ffd83dbSDimitry Andric Prev->Tok.getLocation().getLocWithOffset(Prev->TokenText.size()); 26045ffd83dbSDimitry Andric // If inserting a comma would push the code over the column limit, skip 26055ffd83dbSDimitry Andric // this location - it'd introduce an unstable formatting due to the 26065ffd83dbSDimitry Andric // required reflow. 26075ffd83dbSDimitry Andric unsigned ColumnNumber = 26085ffd83dbSDimitry Andric Env.getSourceManager().getSpellingColumnNumber(Start); 26095ffd83dbSDimitry Andric if (ColumnNumber > Style.ColumnLimit) 26105ffd83dbSDimitry Andric continue; 26115ffd83dbSDimitry Andric // Comma insertions cannot conflict with each other, and this pass has a 26125ffd83dbSDimitry Andric // clean set of Replacements, so the operation below cannot fail. 26135ffd83dbSDimitry Andric cantFail(Result.add( 26145ffd83dbSDimitry Andric tooling::Replacement(Env.getSourceManager(), Start, 0, ","))); 26155ffd83dbSDimitry Andric } 26165ffd83dbSDimitry Andric } 26175ffd83dbSDimitry Andric } 26185ffd83dbSDimitry Andric }; 26195ffd83dbSDimitry Andric 26200b57cec5SDimitry Andric // This class clean up the erroneous/redundant code around the given ranges in 26210b57cec5SDimitry Andric // file. 26220b57cec5SDimitry Andric class Cleaner : public TokenAnalyzer { 26230b57cec5SDimitry Andric public: 26240b57cec5SDimitry Andric Cleaner(const Environment &Env, const FormatStyle &Style) 26250b57cec5SDimitry Andric : TokenAnalyzer(Env, Style), 26260b57cec5SDimitry Andric DeletedTokens(FormatTokenLess(Env.getSourceManager())) {} 26270b57cec5SDimitry Andric 26280b57cec5SDimitry Andric // FIXME: eliminate unused parameters. 26290b57cec5SDimitry Andric std::pair<tooling::Replacements, unsigned> 26300b57cec5SDimitry Andric analyze(TokenAnnotator &Annotator, 26310b57cec5SDimitry Andric SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 26320b57cec5SDimitry Andric FormatTokenLexer &Tokens) override { 26330b57cec5SDimitry Andric // FIXME: in the current implementation the granularity of affected range 26340b57cec5SDimitry Andric // is an annotated line. However, this is not sufficient. Furthermore, 26350b57cec5SDimitry Andric // redundant code introduced by replacements does not necessarily 26360b57cec5SDimitry Andric // intercept with ranges of replacements that result in the redundancy. 26370b57cec5SDimitry Andric // To determine if some redundant code is actually introduced by 26380b57cec5SDimitry Andric // replacements(e.g. deletions), we need to come up with a more 26390b57cec5SDimitry Andric // sophisticated way of computing affected ranges. 26400b57cec5SDimitry Andric AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 26410b57cec5SDimitry Andric 26420b57cec5SDimitry Andric checkEmptyNamespace(AnnotatedLines); 26430b57cec5SDimitry Andric 2644a7dea167SDimitry Andric for (auto *Line : AnnotatedLines) 2645a7dea167SDimitry Andric cleanupLine(Line); 2646a7dea167SDimitry Andric 2647a7dea167SDimitry Andric return {generateFixes(), 0}; 2648a7dea167SDimitry Andric } 2649a7dea167SDimitry Andric 2650a7dea167SDimitry Andric private: 2651a7dea167SDimitry Andric void cleanupLine(AnnotatedLine *Line) { 265281ad6265SDimitry Andric for (auto *Child : Line->Children) 2653a7dea167SDimitry Andric cleanupLine(Child); 2654a7dea167SDimitry Andric 26550b57cec5SDimitry Andric if (Line->Affected) { 26560b57cec5SDimitry Andric cleanupRight(Line->First, tok::comma, tok::comma); 26570b57cec5SDimitry Andric cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma); 26580b57cec5SDimitry Andric cleanupRight(Line->First, tok::l_paren, tok::comma); 26590b57cec5SDimitry Andric cleanupLeft(Line->First, tok::comma, tok::r_paren); 26600b57cec5SDimitry Andric cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace); 26610b57cec5SDimitry Andric cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace); 26620b57cec5SDimitry Andric cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal); 26630b57cec5SDimitry Andric } 26640b57cec5SDimitry Andric } 26650b57cec5SDimitry Andric 26660b57cec5SDimitry Andric bool containsOnlyComments(const AnnotatedLine &Line) { 266706c3fb27SDimitry Andric for (FormatToken *Tok = Line.First; Tok; Tok = Tok->Next) 26680b57cec5SDimitry Andric if (Tok->isNot(tok::comment)) 26690b57cec5SDimitry Andric return false; 26700b57cec5SDimitry Andric return true; 26710b57cec5SDimitry Andric } 26720b57cec5SDimitry Andric 26730b57cec5SDimitry Andric // Iterate through all lines and remove any empty (nested) namespaces. 26740b57cec5SDimitry Andric void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { 26750b57cec5SDimitry Andric std::set<unsigned> DeletedLines; 26760b57cec5SDimitry Andric for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { 26770b57cec5SDimitry Andric auto &Line = *AnnotatedLines[i]; 267881ad6265SDimitry Andric if (Line.startsWithNamespace()) 26790b57cec5SDimitry Andric checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines); 26800b57cec5SDimitry Andric } 26810b57cec5SDimitry Andric 26820b57cec5SDimitry Andric for (auto Line : DeletedLines) { 26830b57cec5SDimitry Andric FormatToken *Tok = AnnotatedLines[Line]->First; 26840b57cec5SDimitry Andric while (Tok) { 26850b57cec5SDimitry Andric deleteToken(Tok); 26860b57cec5SDimitry Andric Tok = Tok->Next; 26870b57cec5SDimitry Andric } 26880b57cec5SDimitry Andric } 26890b57cec5SDimitry Andric } 26900b57cec5SDimitry Andric 26910b57cec5SDimitry Andric // The function checks if the namespace, which starts from \p CurrentLine, and 26920b57cec5SDimitry Andric // its nested namespaces are empty and delete them if they are empty. It also 26930b57cec5SDimitry Andric // sets \p NewLine to the last line checked. 26940b57cec5SDimitry Andric // Returns true if the current namespace is empty. 26950b57cec5SDimitry Andric bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 26960b57cec5SDimitry Andric unsigned CurrentLine, unsigned &NewLine, 26970b57cec5SDimitry Andric std::set<unsigned> &DeletedLines) { 26980b57cec5SDimitry Andric unsigned InitLine = CurrentLine, End = AnnotatedLines.size(); 26990b57cec5SDimitry Andric if (Style.BraceWrapping.AfterNamespace) { 27000b57cec5SDimitry Andric // If the left brace is in a new line, we should consume it first so that 27010b57cec5SDimitry Andric // it does not make the namespace non-empty. 27020b57cec5SDimitry Andric // FIXME: error handling if there is no left brace. 27030b57cec5SDimitry Andric if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) { 27040b57cec5SDimitry Andric NewLine = CurrentLine; 27050b57cec5SDimitry Andric return false; 27060b57cec5SDimitry Andric } 27070b57cec5SDimitry Andric } else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) { 27080b57cec5SDimitry Andric return false; 27090b57cec5SDimitry Andric } 27100b57cec5SDimitry Andric while (++CurrentLine < End) { 27110b57cec5SDimitry Andric if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace)) 27120b57cec5SDimitry Andric break; 27130b57cec5SDimitry Andric 27140b57cec5SDimitry Andric if (AnnotatedLines[CurrentLine]->startsWithNamespace()) { 27150b57cec5SDimitry Andric if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine, 271681ad6265SDimitry Andric DeletedLines)) { 27170b57cec5SDimitry Andric return false; 271881ad6265SDimitry Andric } 27190b57cec5SDimitry Andric CurrentLine = NewLine; 27200b57cec5SDimitry Andric continue; 27210b57cec5SDimitry Andric } 27220b57cec5SDimitry Andric 27230b57cec5SDimitry Andric if (containsOnlyComments(*AnnotatedLines[CurrentLine])) 27240b57cec5SDimitry Andric continue; 27250b57cec5SDimitry Andric 27260b57cec5SDimitry Andric // If there is anything other than comments or nested namespaces in the 27270b57cec5SDimitry Andric // current namespace, the namespace cannot be empty. 27280b57cec5SDimitry Andric NewLine = CurrentLine; 27290b57cec5SDimitry Andric return false; 27300b57cec5SDimitry Andric } 27310b57cec5SDimitry Andric 27320b57cec5SDimitry Andric NewLine = CurrentLine; 27330b57cec5SDimitry Andric if (CurrentLine >= End) 27340b57cec5SDimitry Andric return false; 27350b57cec5SDimitry Andric 27360b57cec5SDimitry Andric // Check if the empty namespace is actually affected by changed ranges. 27370b57cec5SDimitry Andric if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange( 27380b57cec5SDimitry Andric AnnotatedLines[InitLine]->First->Tok.getLocation(), 273981ad6265SDimitry Andric AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc()))) { 27400b57cec5SDimitry Andric return false; 27410b57cec5SDimitry Andric } 27420b57cec5SDimitry Andric 274381ad6265SDimitry Andric for (unsigned i = InitLine; i <= CurrentLine; ++i) 274481ad6265SDimitry Andric DeletedLines.insert(i); 274581ad6265SDimitry Andric 27460b57cec5SDimitry Andric return true; 27470b57cec5SDimitry Andric } 27480b57cec5SDimitry Andric 27490b57cec5SDimitry Andric // Checks pairs {start, start->next},..., {end->previous, end} and deletes one 27500b57cec5SDimitry Andric // of the token in the pair if the left token has \p LK token kind and the 27510b57cec5SDimitry Andric // right token has \p RK token kind. If \p DeleteLeft is true, the left token 27520b57cec5SDimitry Andric // is deleted on match; otherwise, the right token is deleted. 27530b57cec5SDimitry Andric template <typename LeftKind, typename RightKind> 27540b57cec5SDimitry Andric void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK, 27550b57cec5SDimitry Andric bool DeleteLeft) { 27560b57cec5SDimitry Andric auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * { 275781ad6265SDimitry Andric for (auto *Res = Tok.Next; Res; Res = Res->Next) { 27585f757f3fSDimitry Andric if (Res->isNot(tok::comment) && 275981ad6265SDimitry Andric DeletedTokens.find(Res) == DeletedTokens.end()) { 27600b57cec5SDimitry Andric return Res; 276181ad6265SDimitry Andric } 276281ad6265SDimitry Andric } 27630b57cec5SDimitry Andric return nullptr; 27640b57cec5SDimitry Andric }; 27650b57cec5SDimitry Andric for (auto *Left = Start; Left;) { 27660b57cec5SDimitry Andric auto *Right = NextNotDeleted(*Left); 27670b57cec5SDimitry Andric if (!Right) 27680b57cec5SDimitry Andric break; 27690b57cec5SDimitry Andric if (Left->is(LK) && Right->is(RK)) { 27700b57cec5SDimitry Andric deleteToken(DeleteLeft ? Left : Right); 27710b57cec5SDimitry Andric for (auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next) 27720b57cec5SDimitry Andric deleteToken(Tok); 27730b57cec5SDimitry Andric // If the right token is deleted, we should keep the left token 27740b57cec5SDimitry Andric // unchanged and pair it with the new right token. 27750b57cec5SDimitry Andric if (!DeleteLeft) 27760b57cec5SDimitry Andric continue; 27770b57cec5SDimitry Andric } 27780b57cec5SDimitry Andric Left = Right; 27790b57cec5SDimitry Andric } 27800b57cec5SDimitry Andric } 27810b57cec5SDimitry Andric 27820b57cec5SDimitry Andric template <typename LeftKind, typename RightKind> 27830b57cec5SDimitry Andric void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) { 27840b57cec5SDimitry Andric cleanupPair(Start, LK, RK, /*DeleteLeft=*/true); 27850b57cec5SDimitry Andric } 27860b57cec5SDimitry Andric 27870b57cec5SDimitry Andric template <typename LeftKind, typename RightKind> 27880b57cec5SDimitry Andric void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) { 27890b57cec5SDimitry Andric cleanupPair(Start, LK, RK, /*DeleteLeft=*/false); 27900b57cec5SDimitry Andric } 27910b57cec5SDimitry Andric 27920b57cec5SDimitry Andric // Delete the given token. 27930b57cec5SDimitry Andric inline void deleteToken(FormatToken *Tok) { 27940b57cec5SDimitry Andric if (Tok) 27950b57cec5SDimitry Andric DeletedTokens.insert(Tok); 27960b57cec5SDimitry Andric } 27970b57cec5SDimitry Andric 27980b57cec5SDimitry Andric tooling::Replacements generateFixes() { 27990b57cec5SDimitry Andric tooling::Replacements Fixes; 2800753f127fSDimitry Andric SmallVector<FormatToken *> Tokens; 28010b57cec5SDimitry Andric std::copy(DeletedTokens.begin(), DeletedTokens.end(), 28020b57cec5SDimitry Andric std::back_inserter(Tokens)); 28030b57cec5SDimitry Andric 28040b57cec5SDimitry Andric // Merge multiple continuous token deletions into one big deletion so that 28050b57cec5SDimitry Andric // the number of replacements can be reduced. This makes computing affected 28060b57cec5SDimitry Andric // ranges more efficient when we run reformat on the changed code. 28070b57cec5SDimitry Andric unsigned Idx = 0; 28080b57cec5SDimitry Andric while (Idx < Tokens.size()) { 28090b57cec5SDimitry Andric unsigned St = Idx, End = Idx; 281081ad6265SDimitry Andric while ((End + 1) < Tokens.size() && Tokens[End]->Next == Tokens[End + 1]) 281104eeddc0SDimitry Andric ++End; 28120b57cec5SDimitry Andric auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(), 28130b57cec5SDimitry Andric Tokens[End]->Tok.getEndLoc()); 28140b57cec5SDimitry Andric auto Err = 28150b57cec5SDimitry Andric Fixes.add(tooling::Replacement(Env.getSourceManager(), SR, "")); 28160b57cec5SDimitry Andric // FIXME: better error handling. for now just print error message and skip 28170b57cec5SDimitry Andric // for the release version. 28180b57cec5SDimitry Andric if (Err) { 2819*0fca6ea1SDimitry Andric llvm::errs() << toString(std::move(Err)) << "\n"; 28200b57cec5SDimitry Andric assert(false && "Fixes must not conflict!"); 28210b57cec5SDimitry Andric } 28220b57cec5SDimitry Andric Idx = End + 1; 28230b57cec5SDimitry Andric } 28240b57cec5SDimitry Andric 28250b57cec5SDimitry Andric return Fixes; 28260b57cec5SDimitry Andric } 28270b57cec5SDimitry Andric 28280b57cec5SDimitry Andric // Class for less-than inequality comparason for the set `RedundantTokens`. 28290b57cec5SDimitry Andric // We store tokens in the order they appear in the translation unit so that 28300b57cec5SDimitry Andric // we do not need to sort them in `generateFixes()`. 28310b57cec5SDimitry Andric struct FormatTokenLess { 28320b57cec5SDimitry Andric FormatTokenLess(const SourceManager &SM) : SM(SM) {} 28330b57cec5SDimitry Andric 28340b57cec5SDimitry Andric bool operator()(const FormatToken *LHS, const FormatToken *RHS) const { 28350b57cec5SDimitry Andric return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(), 28360b57cec5SDimitry Andric RHS->Tok.getLocation()); 28370b57cec5SDimitry Andric } 28380b57cec5SDimitry Andric const SourceManager &SM; 28390b57cec5SDimitry Andric }; 28400b57cec5SDimitry Andric 28410b57cec5SDimitry Andric // Tokens to be deleted. 28420b57cec5SDimitry Andric std::set<FormatToken *, FormatTokenLess> DeletedTokens; 28430b57cec5SDimitry Andric }; 28440b57cec5SDimitry Andric 28450b57cec5SDimitry Andric class ObjCHeaderStyleGuesser : public TokenAnalyzer { 28460b57cec5SDimitry Andric public: 28470b57cec5SDimitry Andric ObjCHeaderStyleGuesser(const Environment &Env, const FormatStyle &Style) 28480b57cec5SDimitry Andric : TokenAnalyzer(Env, Style), IsObjC(false) {} 28490b57cec5SDimitry Andric 28500b57cec5SDimitry Andric std::pair<tooling::Replacements, unsigned> 28510b57cec5SDimitry Andric analyze(TokenAnnotator &Annotator, 28520b57cec5SDimitry Andric SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 28530b57cec5SDimitry Andric FormatTokenLexer &Tokens) override { 28540b57cec5SDimitry Andric assert(Style.Language == FormatStyle::LK_Cpp); 28550b57cec5SDimitry Andric IsObjC = guessIsObjC(Env.getSourceManager(), AnnotatedLines, 28560b57cec5SDimitry Andric Tokens.getKeywords()); 28570b57cec5SDimitry Andric tooling::Replacements Result; 28580b57cec5SDimitry Andric return {Result, 0}; 28590b57cec5SDimitry Andric } 28600b57cec5SDimitry Andric 28610b57cec5SDimitry Andric bool isObjC() { return IsObjC; } 28620b57cec5SDimitry Andric 28630b57cec5SDimitry Andric private: 28640b57cec5SDimitry Andric static bool 28650b57cec5SDimitry Andric guessIsObjC(const SourceManager &SourceManager, 28660b57cec5SDimitry Andric const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 28670b57cec5SDimitry Andric const AdditionalKeywords &Keywords) { 28680b57cec5SDimitry Andric // Keep this array sorted, since we are binary searching over it. 28690b57cec5SDimitry Andric static constexpr llvm::StringLiteral FoundationIdentifiers[] = { 28700b57cec5SDimitry Andric "CGFloat", 28710b57cec5SDimitry Andric "CGPoint", 28720b57cec5SDimitry Andric "CGPointMake", 28730b57cec5SDimitry Andric "CGPointZero", 28740b57cec5SDimitry Andric "CGRect", 28750b57cec5SDimitry Andric "CGRectEdge", 28760b57cec5SDimitry Andric "CGRectInfinite", 28770b57cec5SDimitry Andric "CGRectMake", 28780b57cec5SDimitry Andric "CGRectNull", 28790b57cec5SDimitry Andric "CGRectZero", 28800b57cec5SDimitry Andric "CGSize", 28810b57cec5SDimitry Andric "CGSizeMake", 28820b57cec5SDimitry Andric "CGVector", 28830b57cec5SDimitry Andric "CGVectorMake", 288406c3fb27SDimitry Andric "FOUNDATION_EXPORT", // This is an alias for FOUNDATION_EXTERN. 288506c3fb27SDimitry Andric "FOUNDATION_EXTERN", 28860b57cec5SDimitry Andric "NSAffineTransform", 28870b57cec5SDimitry Andric "NSArray", 28880b57cec5SDimitry Andric "NSAttributedString", 28890b57cec5SDimitry Andric "NSBlockOperation", 28900b57cec5SDimitry Andric "NSBundle", 28910b57cec5SDimitry Andric "NSCache", 28920b57cec5SDimitry Andric "NSCalendar", 28930b57cec5SDimitry Andric "NSCharacterSet", 28940b57cec5SDimitry Andric "NSCountedSet", 28950b57cec5SDimitry Andric "NSData", 28960b57cec5SDimitry Andric "NSDataDetector", 28970b57cec5SDimitry Andric "NSDecimal", 28980b57cec5SDimitry Andric "NSDecimalNumber", 28990b57cec5SDimitry Andric "NSDictionary", 29000b57cec5SDimitry Andric "NSEdgeInsets", 290106c3fb27SDimitry Andric "NSError", 290206c3fb27SDimitry Andric "NSErrorDomain", 29030b57cec5SDimitry Andric "NSHashTable", 29040b57cec5SDimitry Andric "NSIndexPath", 29050b57cec5SDimitry Andric "NSIndexSet", 29060b57cec5SDimitry Andric "NSInteger", 29070b57cec5SDimitry Andric "NSInvocationOperation", 29080b57cec5SDimitry Andric "NSLocale", 29090b57cec5SDimitry Andric "NSMapTable", 29100b57cec5SDimitry Andric "NSMutableArray", 29110b57cec5SDimitry Andric "NSMutableAttributedString", 29120b57cec5SDimitry Andric "NSMutableCharacterSet", 29130b57cec5SDimitry Andric "NSMutableData", 29140b57cec5SDimitry Andric "NSMutableDictionary", 29150b57cec5SDimitry Andric "NSMutableIndexSet", 29160b57cec5SDimitry Andric "NSMutableOrderedSet", 29170b57cec5SDimitry Andric "NSMutableSet", 29180b57cec5SDimitry Andric "NSMutableString", 29190b57cec5SDimitry Andric "NSNumber", 29200b57cec5SDimitry Andric "NSNumberFormatter", 29210b57cec5SDimitry Andric "NSObject", 29220b57cec5SDimitry Andric "NSOperation", 29230b57cec5SDimitry Andric "NSOperationQueue", 29240b57cec5SDimitry Andric "NSOperationQueuePriority", 29250b57cec5SDimitry Andric "NSOrderedSet", 29260b57cec5SDimitry Andric "NSPoint", 29270b57cec5SDimitry Andric "NSPointerArray", 29280b57cec5SDimitry Andric "NSQualityOfService", 29290b57cec5SDimitry Andric "NSRange", 29300b57cec5SDimitry Andric "NSRect", 29310b57cec5SDimitry Andric "NSRegularExpression", 29320b57cec5SDimitry Andric "NSSet", 29330b57cec5SDimitry Andric "NSSize", 29340b57cec5SDimitry Andric "NSString", 29350b57cec5SDimitry Andric "NSTimeZone", 29360b57cec5SDimitry Andric "NSUInteger", 29370b57cec5SDimitry Andric "NSURL", 29380b57cec5SDimitry Andric "NSURLComponents", 29390b57cec5SDimitry Andric "NSURLQueryItem", 29400b57cec5SDimitry Andric "NSUUID", 29410b57cec5SDimitry Andric "NSValue", 294206c3fb27SDimitry Andric "NS_ASSUME_NONNULL_BEGIN", 29430b57cec5SDimitry Andric "UIImage", 29440b57cec5SDimitry Andric "UIView", 29450b57cec5SDimitry Andric }; 29460b57cec5SDimitry Andric 2947bdd1243dSDimitry Andric for (auto *Line : AnnotatedLines) { 29485f757f3fSDimitry Andric if (Line->First && (Line->First->TokenText.starts_with("#") || 2949e8d8bef9SDimitry Andric Line->First->TokenText == "__pragma" || 295081ad6265SDimitry Andric Line->First->TokenText == "_Pragma")) { 2951e8d8bef9SDimitry Andric continue; 295281ad6265SDimitry Andric } 29530b57cec5SDimitry Andric for (const FormatToken *FormatTok = Line->First; FormatTok; 29540b57cec5SDimitry Andric FormatTok = FormatTok->Next) { 29550b57cec5SDimitry Andric if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) && 29560b57cec5SDimitry Andric (FormatTok->Tok.getObjCKeywordID() != tok::objc_not_keyword || 29570b57cec5SDimitry Andric FormatTok->isOneOf(tok::numeric_constant, tok::l_square, 29580b57cec5SDimitry Andric tok::l_brace))) || 29590b57cec5SDimitry Andric (FormatTok->Tok.isAnyIdentifier() && 29600b57cec5SDimitry Andric std::binary_search(std::begin(FoundationIdentifiers), 29610b57cec5SDimitry Andric std::end(FoundationIdentifiers), 29620b57cec5SDimitry Andric FormatTok->TokenText)) || 29630b57cec5SDimitry Andric FormatTok->is(TT_ObjCStringLiteral) || 2964a7dea167SDimitry Andric FormatTok->isOneOf(Keywords.kw_NS_CLOSED_ENUM, Keywords.kw_NS_ENUM, 296506c3fb27SDimitry Andric Keywords.kw_NS_ERROR_ENUM, 2966a7dea167SDimitry Andric Keywords.kw_NS_OPTIONS, TT_ObjCBlockLBrace, 2967a7dea167SDimitry Andric TT_ObjCBlockLParen, TT_ObjCDecl, TT_ObjCForIn, 2968a7dea167SDimitry Andric TT_ObjCMethodExpr, TT_ObjCMethodSpecifier, 2969a7dea167SDimitry Andric TT_ObjCProperty)) { 29700b57cec5SDimitry Andric LLVM_DEBUG(llvm::dbgs() 29710b57cec5SDimitry Andric << "Detected ObjC at location " 29720b57cec5SDimitry Andric << FormatTok->Tok.getLocation().printToString( 29730b57cec5SDimitry Andric SourceManager) 29740b57cec5SDimitry Andric << " token: " << FormatTok->TokenText << " token type: " 29755ffd83dbSDimitry Andric << getTokenTypeName(FormatTok->getType()) << "\n"); 29760b57cec5SDimitry Andric return true; 29770b57cec5SDimitry Andric } 2978*0fca6ea1SDimitry Andric } 29790b57cec5SDimitry Andric if (guessIsObjC(SourceManager, Line->Children, Keywords)) 29800b57cec5SDimitry Andric return true; 29810b57cec5SDimitry Andric } 29820b57cec5SDimitry Andric return false; 29830b57cec5SDimitry Andric } 29840b57cec5SDimitry Andric 29850b57cec5SDimitry Andric bool IsObjC; 29860b57cec5SDimitry Andric }; 29870b57cec5SDimitry Andric 29880b57cec5SDimitry Andric struct IncludeDirective { 29890b57cec5SDimitry Andric StringRef Filename; 29900b57cec5SDimitry Andric StringRef Text; 29910b57cec5SDimitry Andric unsigned Offset; 29920b57cec5SDimitry Andric int Category; 2993a7dea167SDimitry Andric int Priority; 29940b57cec5SDimitry Andric }; 29950b57cec5SDimitry Andric 29960b57cec5SDimitry Andric struct JavaImportDirective { 29970b57cec5SDimitry Andric StringRef Identifier; 29980b57cec5SDimitry Andric StringRef Text; 29990b57cec5SDimitry Andric unsigned Offset; 3000753f127fSDimitry Andric SmallVector<StringRef> AssociatedCommentLines; 30010b57cec5SDimitry Andric bool IsStatic; 30020b57cec5SDimitry Andric }; 30030b57cec5SDimitry Andric 30040b57cec5SDimitry Andric } // end anonymous namespace 30050b57cec5SDimitry Andric 30060b57cec5SDimitry Andric // Determines whether 'Ranges' intersects with ('Start', 'End'). 30070b57cec5SDimitry Andric static bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start, 30080b57cec5SDimitry Andric unsigned End) { 300906c3fb27SDimitry Andric for (const auto &Range : Ranges) { 30100b57cec5SDimitry Andric if (Range.getOffset() < End && 301181ad6265SDimitry Andric Range.getOffset() + Range.getLength() > Start) { 30120b57cec5SDimitry Andric return true; 30130b57cec5SDimitry Andric } 301481ad6265SDimitry Andric } 30150b57cec5SDimitry Andric return false; 30160b57cec5SDimitry Andric } 30170b57cec5SDimitry Andric 30180b57cec5SDimitry Andric // Returns a pair (Index, OffsetToEOL) describing the position of the cursor 30190b57cec5SDimitry Andric // before sorting/deduplicating. Index is the index of the include under the 30200b57cec5SDimitry Andric // cursor in the original set of includes. If this include has duplicates, it is 30210b57cec5SDimitry Andric // the index of the first of the duplicates as the others are going to be 30220b57cec5SDimitry Andric // removed. OffsetToEOL describes the cursor's position relative to the end of 30230b57cec5SDimitry Andric // its current line. 30240b57cec5SDimitry Andric // If `Cursor` is not on any #include, `Index` will be UINT_MAX. 30250b57cec5SDimitry Andric static std::pair<unsigned, unsigned> 30260b57cec5SDimitry Andric FindCursorIndex(const SmallVectorImpl<IncludeDirective> &Includes, 30270b57cec5SDimitry Andric const SmallVectorImpl<unsigned> &Indices, unsigned Cursor) { 30280b57cec5SDimitry Andric unsigned CursorIndex = UINT_MAX; 30290b57cec5SDimitry Andric unsigned OffsetToEOL = 0; 30300b57cec5SDimitry Andric for (int i = 0, e = Includes.size(); i != e; ++i) { 30310b57cec5SDimitry Andric unsigned Start = Includes[Indices[i]].Offset; 30320b57cec5SDimitry Andric unsigned End = Start + Includes[Indices[i]].Text.size(); 30330b57cec5SDimitry Andric if (!(Cursor >= Start && Cursor < End)) 30340b57cec5SDimitry Andric continue; 30350b57cec5SDimitry Andric CursorIndex = Indices[i]; 30360b57cec5SDimitry Andric OffsetToEOL = End - Cursor; 30370b57cec5SDimitry Andric // Put the cursor on the only remaining #include among the duplicate 30380b57cec5SDimitry Andric // #includes. 30390b57cec5SDimitry Andric while (--i >= 0 && Includes[CursorIndex].Text == Includes[Indices[i]].Text) 30400b57cec5SDimitry Andric CursorIndex = i; 30410b57cec5SDimitry Andric break; 30420b57cec5SDimitry Andric } 30430b57cec5SDimitry Andric return std::make_pair(CursorIndex, OffsetToEOL); 30440b57cec5SDimitry Andric } 30450b57cec5SDimitry Andric 3046a7dea167SDimitry Andric // Replace all "\r\n" with "\n". 3047a7dea167SDimitry Andric std::string replaceCRLF(const std::string &Code) { 3048a7dea167SDimitry Andric std::string NewCode; 3049a7dea167SDimitry Andric size_t Pos = 0, LastPos = 0; 3050a7dea167SDimitry Andric 3051a7dea167SDimitry Andric do { 3052a7dea167SDimitry Andric Pos = Code.find("\r\n", LastPos); 3053a7dea167SDimitry Andric if (Pos == LastPos) { 305404eeddc0SDimitry Andric ++LastPos; 3055a7dea167SDimitry Andric continue; 3056a7dea167SDimitry Andric } 3057a7dea167SDimitry Andric if (Pos == std::string::npos) { 3058a7dea167SDimitry Andric NewCode += Code.substr(LastPos); 3059a7dea167SDimitry Andric break; 3060a7dea167SDimitry Andric } 3061a7dea167SDimitry Andric NewCode += Code.substr(LastPos, Pos - LastPos) + "\n"; 3062a7dea167SDimitry Andric LastPos = Pos + 2; 3063a7dea167SDimitry Andric } while (Pos != std::string::npos); 3064a7dea167SDimitry Andric 3065a7dea167SDimitry Andric return NewCode; 3066a7dea167SDimitry Andric } 3067a7dea167SDimitry Andric 30680b57cec5SDimitry Andric // Sorts and deduplicate a block of includes given by 'Includes' alphabetically 30690b57cec5SDimitry Andric // adding the necessary replacement to 'Replaces'. 'Includes' must be in strict 30700b57cec5SDimitry Andric // source order. 30710b57cec5SDimitry Andric // #include directives with the same text will be deduplicated, and only the 30720b57cec5SDimitry Andric // first #include in the duplicate #includes remains. If the `Cursor` is 30730b57cec5SDimitry Andric // provided and put on a deleted #include, it will be moved to the remaining 30740b57cec5SDimitry Andric // #include in the duplicate #includes. 30750b57cec5SDimitry Andric static void sortCppIncludes(const FormatStyle &Style, 30760b57cec5SDimitry Andric const SmallVectorImpl<IncludeDirective> &Includes, 30770b57cec5SDimitry Andric ArrayRef<tooling::Range> Ranges, StringRef FileName, 3078a7dea167SDimitry Andric StringRef Code, tooling::Replacements &Replaces, 3079a7dea167SDimitry Andric unsigned *Cursor) { 3080a7dea167SDimitry Andric tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName); 308181ad6265SDimitry Andric const unsigned IncludesBeginOffset = Includes.front().Offset; 308281ad6265SDimitry Andric const unsigned IncludesEndOffset = 30830b57cec5SDimitry Andric Includes.back().Offset + Includes.back().Text.size(); 308481ad6265SDimitry Andric const unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset; 30850b57cec5SDimitry Andric if (!affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset)) 30860b57cec5SDimitry Andric return; 308781ad6265SDimitry Andric SmallVector<unsigned, 16> Indices = 308881ad6265SDimitry Andric llvm::to_vector<16>(llvm::seq<unsigned>(0, Includes.size())); 3089fe6060f1SDimitry Andric 3090fe6060f1SDimitry Andric if (Style.SortIncludes == FormatStyle::SI_CaseInsensitive) { 3091*0fca6ea1SDimitry Andric stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) { 3092fe6060f1SDimitry Andric const auto LHSFilenameLower = Includes[LHSI].Filename.lower(); 3093fe6060f1SDimitry Andric const auto RHSFilenameLower = Includes[RHSI].Filename.lower(); 3094fe6060f1SDimitry Andric return std::tie(Includes[LHSI].Priority, LHSFilenameLower, 3095fe6060f1SDimitry Andric Includes[LHSI].Filename) < 3096fe6060f1SDimitry Andric std::tie(Includes[RHSI].Priority, RHSFilenameLower, 3097fe6060f1SDimitry Andric Includes[RHSI].Filename); 3098fe6060f1SDimitry Andric }); 3099fe6060f1SDimitry Andric } else { 3100*0fca6ea1SDimitry Andric stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) { 3101a7dea167SDimitry Andric return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) < 3102a7dea167SDimitry Andric std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename); 31030b57cec5SDimitry Andric }); 3104fe6060f1SDimitry Andric } 3105fe6060f1SDimitry Andric 31060b57cec5SDimitry Andric // The index of the include on which the cursor will be put after 31070b57cec5SDimitry Andric // sorting/deduplicating. 31080b57cec5SDimitry Andric unsigned CursorIndex; 31090b57cec5SDimitry Andric // The offset from cursor to the end of line. 31100b57cec5SDimitry Andric unsigned CursorToEOLOffset; 311181ad6265SDimitry Andric if (Cursor) { 31120b57cec5SDimitry Andric std::tie(CursorIndex, CursorToEOLOffset) = 31130b57cec5SDimitry Andric FindCursorIndex(Includes, Indices, *Cursor); 311481ad6265SDimitry Andric } 31150b57cec5SDimitry Andric 31160b57cec5SDimitry Andric // Deduplicate #includes. 31170b57cec5SDimitry Andric Indices.erase(std::unique(Indices.begin(), Indices.end(), 31180b57cec5SDimitry Andric [&](unsigned LHSI, unsigned RHSI) { 3119e8d8bef9SDimitry Andric return Includes[LHSI].Text.trim() == 3120e8d8bef9SDimitry Andric Includes[RHSI].Text.trim(); 31210b57cec5SDimitry Andric }), 31220b57cec5SDimitry Andric Indices.end()); 31230b57cec5SDimitry Andric 31240b57cec5SDimitry Andric int CurrentCategory = Includes.front().Category; 31250b57cec5SDimitry Andric 31260b57cec5SDimitry Andric // If the #includes are out of order, we generate a single replacement fixing 31270b57cec5SDimitry Andric // the entire block. Otherwise, no replacement is generated. 31280b57cec5SDimitry Andric // In case Style.IncldueStyle.IncludeBlocks != IBS_Preserve, this check is not 31290b57cec5SDimitry Andric // enough as additional newlines might be added or removed across #include 313081ad6265SDimitry Andric // blocks. This we handle below by generating the updated #include blocks and 31310b57cec5SDimitry Andric // comparing it to the original. 3132*0fca6ea1SDimitry Andric if (Indices.size() == Includes.size() && is_sorted(Indices) && 313381ad6265SDimitry Andric Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Preserve) { 31340b57cec5SDimitry Andric return; 313581ad6265SDimitry Andric } 31360b57cec5SDimitry Andric 3137*0fca6ea1SDimitry Andric const auto OldCursor = Cursor ? *Cursor : 0; 31380b57cec5SDimitry Andric std::string result; 31390b57cec5SDimitry Andric for (unsigned Index : Indices) { 31400b57cec5SDimitry Andric if (!result.empty()) { 31410b57cec5SDimitry Andric result += "\n"; 31420b57cec5SDimitry Andric if (Style.IncludeStyle.IncludeBlocks == 31430b57cec5SDimitry Andric tooling::IncludeStyle::IBS_Regroup && 314481ad6265SDimitry Andric CurrentCategory != Includes[Index].Category) { 31450b57cec5SDimitry Andric result += "\n"; 31460b57cec5SDimitry Andric } 314781ad6265SDimitry Andric } 31480b57cec5SDimitry Andric result += Includes[Index].Text; 31490b57cec5SDimitry Andric if (Cursor && CursorIndex == Index) 31500b57cec5SDimitry Andric *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset; 31510b57cec5SDimitry Andric CurrentCategory = Includes[Index].Category; 31520b57cec5SDimitry Andric } 31530b57cec5SDimitry Andric 315481ad6265SDimitry Andric if (Cursor && *Cursor >= IncludesEndOffset) 315581ad6265SDimitry Andric *Cursor += result.size() - IncludesBlockSize; 315681ad6265SDimitry Andric 31570b57cec5SDimitry Andric // If the #includes are out of order, we generate a single replacement fixing 31580b57cec5SDimitry Andric // the entire range of blocks. Otherwise, no replacement is generated. 31595ffd83dbSDimitry Andric if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr( 316081ad6265SDimitry Andric IncludesBeginOffset, IncludesBlockSize)))) { 3161*0fca6ea1SDimitry Andric if (Cursor) 3162*0fca6ea1SDimitry Andric *Cursor = OldCursor; 31630b57cec5SDimitry Andric return; 316481ad6265SDimitry Andric } 31650b57cec5SDimitry Andric 31660b57cec5SDimitry Andric auto Err = Replaces.add(tooling::Replacement( 31670b57cec5SDimitry Andric FileName, Includes.front().Offset, IncludesBlockSize, result)); 31680b57cec5SDimitry Andric // FIXME: better error handling. For now, just skip the replacement for the 31690b57cec5SDimitry Andric // release version. 31700b57cec5SDimitry Andric if (Err) { 3171*0fca6ea1SDimitry Andric llvm::errs() << toString(std::move(Err)) << "\n"; 31720b57cec5SDimitry Andric assert(false); 31730b57cec5SDimitry Andric } 31740b57cec5SDimitry Andric } 31750b57cec5SDimitry Andric 31760b57cec5SDimitry Andric tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code, 31770b57cec5SDimitry Andric ArrayRef<tooling::Range> Ranges, 31780b57cec5SDimitry Andric StringRef FileName, 31790b57cec5SDimitry Andric tooling::Replacements &Replaces, 31800b57cec5SDimitry Andric unsigned *Cursor) { 3181e8d8bef9SDimitry Andric unsigned Prev = llvm::StringSwitch<size_t>(Code) 3182e8d8bef9SDimitry Andric .StartsWith("\xEF\xBB\xBF", 3) // UTF-8 BOM 3183e8d8bef9SDimitry Andric .Default(0); 31840b57cec5SDimitry Andric unsigned SearchFrom = 0; 31850b57cec5SDimitry Andric SmallVector<StringRef, 4> Matches; 31860b57cec5SDimitry Andric SmallVector<IncludeDirective, 16> IncludesInBlock; 31870b57cec5SDimitry Andric 31880b57cec5SDimitry Andric // In compiled files, consider the first #include to be the main #include of 31890b57cec5SDimitry Andric // the file if it is not a system #include. This ensures that the header 31900b57cec5SDimitry Andric // doesn't have hidden dependencies 31910b57cec5SDimitry Andric // (http://llvm.org/docs/CodingStandards.html#include-style). 31920b57cec5SDimitry Andric // 31935e801ac6SDimitry Andric // FIXME: Do some validation, e.g. edit distance of the base name, to fix 31940b57cec5SDimitry Andric // cases where the first #include is unlikely to be the main header. 31950b57cec5SDimitry Andric tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName); 31960b57cec5SDimitry Andric bool FirstIncludeBlock = true; 31970b57cec5SDimitry Andric bool MainIncludeFound = false; 31980b57cec5SDimitry Andric bool FormattingOff = false; 31990b57cec5SDimitry Andric 320004eeddc0SDimitry Andric // '[' must be the first and '-' the last character inside [...]. 32010eae32dcSDimitry Andric llvm::Regex RawStringRegex( 320204eeddc0SDimitry Andric "R\"([][A-Za-z0-9_{}#<>%:;.?*+/^&\\$|~!=,'-]*)\\("); 32030eae32dcSDimitry Andric SmallVector<StringRef, 2> RawStringMatches; 32040eae32dcSDimitry Andric std::string RawStringTermination = ")\""; 32050eae32dcSDimitry Andric 32060b57cec5SDimitry Andric for (;;) { 32070b57cec5SDimitry Andric auto Pos = Code.find('\n', SearchFrom); 32080b57cec5SDimitry Andric StringRef Line = 32090b57cec5SDimitry Andric Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev); 32100b57cec5SDimitry Andric 32110b57cec5SDimitry Andric StringRef Trimmed = Line.trim(); 32120eae32dcSDimitry Andric 32130eae32dcSDimitry Andric // #includes inside raw string literals need to be ignored. 32140eae32dcSDimitry Andric // or we will sort the contents of the string. 32150eae32dcSDimitry Andric // Skip past until we think we are at the rawstring literal close. 32160eae32dcSDimitry Andric if (RawStringRegex.match(Trimmed, &RawStringMatches)) { 32170eae32dcSDimitry Andric std::string CharSequence = RawStringMatches[1].str(); 32180eae32dcSDimitry Andric RawStringTermination = ")" + CharSequence + "\""; 32190eae32dcSDimitry Andric FormattingOff = true; 32200eae32dcSDimitry Andric } 32210eae32dcSDimitry Andric 322281ad6265SDimitry Andric if (Trimmed.contains(RawStringTermination)) 322381ad6265SDimitry Andric FormattingOff = false; 322481ad6265SDimitry Andric 3225*0fca6ea1SDimitry Andric bool IsBlockComment = false; 3226*0fca6ea1SDimitry Andric 3227*0fca6ea1SDimitry Andric if (isClangFormatOff(Trimmed)) { 322881ad6265SDimitry Andric FormattingOff = true; 3229*0fca6ea1SDimitry Andric } else if (isClangFormatOn(Trimmed)) { 32300eae32dcSDimitry Andric FormattingOff = false; 3231*0fca6ea1SDimitry Andric } else if (Trimmed.starts_with("/*")) { 3232*0fca6ea1SDimitry Andric IsBlockComment = true; 3233*0fca6ea1SDimitry Andric Pos = Code.find("*/", SearchFrom + 2); 3234*0fca6ea1SDimitry Andric } 32350eae32dcSDimitry Andric 32360b57cec5SDimitry Andric const bool EmptyLineSkipped = 32370b57cec5SDimitry Andric Trimmed.empty() && 32380b57cec5SDimitry Andric (Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Merge || 32390b57cec5SDimitry Andric Style.IncludeStyle.IncludeBlocks == 32400b57cec5SDimitry Andric tooling::IncludeStyle::IBS_Regroup); 32410b57cec5SDimitry Andric 32425f757f3fSDimitry Andric bool MergeWithNextLine = Trimmed.ends_with("\\"); 3243e8d8bef9SDimitry Andric if (!FormattingOff && !MergeWithNextLine) { 3244*0fca6ea1SDimitry Andric if (!IsBlockComment && 3245*0fca6ea1SDimitry Andric tooling::HeaderIncludes::IncludeRegex.match(Trimmed, &Matches)) { 32460b57cec5SDimitry Andric StringRef IncludeName = Matches[2]; 3247*0fca6ea1SDimitry Andric if (Trimmed.contains("/*") && !Trimmed.contains("*/")) { 32481fd87a68SDimitry Andric // #include with a start of a block comment, but without the end. 32491fd87a68SDimitry Andric // Need to keep all the lines until the end of the comment together. 32501fd87a68SDimitry Andric // FIXME: This is somehow simplified check that probably does not work 32511fd87a68SDimitry Andric // correctly if there are multiple comments on a line. 32521fd87a68SDimitry Andric Pos = Code.find("*/", SearchFrom); 32531fd87a68SDimitry Andric Line = Code.substr( 32541fd87a68SDimitry Andric Prev, (Pos != StringRef::npos ? Pos + 2 : Code.size()) - Prev); 32551fd87a68SDimitry Andric } 32560b57cec5SDimitry Andric int Category = Categories.getIncludePriority( 32570b57cec5SDimitry Andric IncludeName, 32580b57cec5SDimitry Andric /*CheckMainHeader=*/!MainIncludeFound && FirstIncludeBlock); 3259a7dea167SDimitry Andric int Priority = Categories.getSortIncludePriority( 3260a7dea167SDimitry Andric IncludeName, !MainIncludeFound && FirstIncludeBlock); 32610b57cec5SDimitry Andric if (Category == 0) 32620b57cec5SDimitry Andric MainIncludeFound = true; 3263a7dea167SDimitry Andric IncludesInBlock.push_back( 3264a7dea167SDimitry Andric {IncludeName, Line, Prev, Category, Priority}); 32650b57cec5SDimitry Andric } else if (!IncludesInBlock.empty() && !EmptyLineSkipped) { 32660b57cec5SDimitry Andric sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, 32670b57cec5SDimitry Andric Replaces, Cursor); 32680b57cec5SDimitry Andric IncludesInBlock.clear(); 32695f757f3fSDimitry Andric if (Trimmed.starts_with("#pragma hdrstop")) // Precompiled headers. 3270e8d8bef9SDimitry Andric FirstIncludeBlock = true; 3271e8d8bef9SDimitry Andric else 32720b57cec5SDimitry Andric FirstIncludeBlock = false; 32730b57cec5SDimitry Andric } 32740b57cec5SDimitry Andric } 32750b57cec5SDimitry Andric if (Pos == StringRef::npos || Pos + 1 == Code.size()) 32760b57cec5SDimitry Andric break; 3277e8d8bef9SDimitry Andric 3278e8d8bef9SDimitry Andric if (!MergeWithNextLine) 3279e8d8bef9SDimitry Andric Prev = Pos + 1; 32800b57cec5SDimitry Andric SearchFrom = Pos + 1; 32810b57cec5SDimitry Andric } 32820b57cec5SDimitry Andric if (!IncludesInBlock.empty()) { 32830b57cec5SDimitry Andric sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, Replaces, 32840b57cec5SDimitry Andric Cursor); 32850b57cec5SDimitry Andric } 32860b57cec5SDimitry Andric return Replaces; 32870b57cec5SDimitry Andric } 32880b57cec5SDimitry Andric 32890b57cec5SDimitry Andric // Returns group number to use as a first order sort on imports. Gives UINT_MAX 32900b57cec5SDimitry Andric // if the import does not match any given groups. 32910b57cec5SDimitry Andric static unsigned findJavaImportGroup(const FormatStyle &Style, 32920b57cec5SDimitry Andric StringRef ImportIdentifier) { 32930b57cec5SDimitry Andric unsigned LongestMatchIndex = UINT_MAX; 32940b57cec5SDimitry Andric unsigned LongestMatchLength = 0; 32950b57cec5SDimitry Andric for (unsigned I = 0; I < Style.JavaImportGroups.size(); I++) { 32961fd87a68SDimitry Andric const std::string &GroupPrefix = Style.JavaImportGroups[I]; 32975f757f3fSDimitry Andric if (ImportIdentifier.starts_with(GroupPrefix) && 32980b57cec5SDimitry Andric GroupPrefix.length() > LongestMatchLength) { 32990b57cec5SDimitry Andric LongestMatchIndex = I; 33000b57cec5SDimitry Andric LongestMatchLength = GroupPrefix.length(); 33010b57cec5SDimitry Andric } 33020b57cec5SDimitry Andric } 33030b57cec5SDimitry Andric return LongestMatchIndex; 33040b57cec5SDimitry Andric } 33050b57cec5SDimitry Andric 33060b57cec5SDimitry Andric // Sorts and deduplicates a block of includes given by 'Imports' based on 33070b57cec5SDimitry Andric // JavaImportGroups, then adding the necessary replacement to 'Replaces'. 33080b57cec5SDimitry Andric // Import declarations with the same text will be deduplicated. Between each 33090b57cec5SDimitry Andric // import group, a newline is inserted, and within each import group, a 33100b57cec5SDimitry Andric // lexicographic sort based on ASCII value is performed. 33110b57cec5SDimitry Andric static void sortJavaImports(const FormatStyle &Style, 33120b57cec5SDimitry Andric const SmallVectorImpl<JavaImportDirective> &Imports, 33130b57cec5SDimitry Andric ArrayRef<tooling::Range> Ranges, StringRef FileName, 33140b57cec5SDimitry Andric StringRef Code, tooling::Replacements &Replaces) { 33150b57cec5SDimitry Andric unsigned ImportsBeginOffset = Imports.front().Offset; 33160b57cec5SDimitry Andric unsigned ImportsEndOffset = 33170b57cec5SDimitry Andric Imports.back().Offset + Imports.back().Text.size(); 33180b57cec5SDimitry Andric unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset; 33190b57cec5SDimitry Andric if (!affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset)) 33200b57cec5SDimitry Andric return; 33211fd87a68SDimitry Andric 332281ad6265SDimitry Andric SmallVector<unsigned, 16> Indices = 332381ad6265SDimitry Andric llvm::to_vector<16>(llvm::seq<unsigned>(0, Imports.size())); 33240b57cec5SDimitry Andric SmallVector<unsigned, 16> JavaImportGroups; 33251fd87a68SDimitry Andric JavaImportGroups.reserve(Imports.size()); 33261fd87a68SDimitry Andric for (const JavaImportDirective &Import : Imports) 33271fd87a68SDimitry Andric JavaImportGroups.push_back(findJavaImportGroup(Style, Import.Identifier)); 33281fd87a68SDimitry Andric 3329e8d8bef9SDimitry Andric bool StaticImportAfterNormalImport = 3330e8d8bef9SDimitry Andric Style.SortJavaStaticImport == FormatStyle::SJSIO_After; 3331*0fca6ea1SDimitry Andric sort(Indices, [&](unsigned LHSI, unsigned RHSI) { 33320b57cec5SDimitry Andric // Negating IsStatic to push static imports above non-static imports. 3333e8d8bef9SDimitry Andric return std::make_tuple(!Imports[LHSI].IsStatic ^ 3334e8d8bef9SDimitry Andric StaticImportAfterNormalImport, 3335e8d8bef9SDimitry Andric JavaImportGroups[LHSI], Imports[LHSI].Identifier) < 3336e8d8bef9SDimitry Andric std::make_tuple(!Imports[RHSI].IsStatic ^ 3337e8d8bef9SDimitry Andric StaticImportAfterNormalImport, 3338e8d8bef9SDimitry Andric JavaImportGroups[RHSI], Imports[RHSI].Identifier); 33390b57cec5SDimitry Andric }); 33400b57cec5SDimitry Andric 33410b57cec5SDimitry Andric // Deduplicate imports. 33420b57cec5SDimitry Andric Indices.erase(std::unique(Indices.begin(), Indices.end(), 33430b57cec5SDimitry Andric [&](unsigned LHSI, unsigned RHSI) { 33440b57cec5SDimitry Andric return Imports[LHSI].Text == Imports[RHSI].Text; 33450b57cec5SDimitry Andric }), 33460b57cec5SDimitry Andric Indices.end()); 33470b57cec5SDimitry Andric 33480b57cec5SDimitry Andric bool CurrentIsStatic = Imports[Indices.front()].IsStatic; 33490b57cec5SDimitry Andric unsigned CurrentImportGroup = JavaImportGroups[Indices.front()]; 33500b57cec5SDimitry Andric 33510b57cec5SDimitry Andric std::string result; 33520b57cec5SDimitry Andric for (unsigned Index : Indices) { 33530b57cec5SDimitry Andric if (!result.empty()) { 33540b57cec5SDimitry Andric result += "\n"; 33550b57cec5SDimitry Andric if (CurrentIsStatic != Imports[Index].IsStatic || 335681ad6265SDimitry Andric CurrentImportGroup != JavaImportGroups[Index]) { 33570b57cec5SDimitry Andric result += "\n"; 33580b57cec5SDimitry Andric } 335981ad6265SDimitry Andric } 33600b57cec5SDimitry Andric for (StringRef CommentLine : Imports[Index].AssociatedCommentLines) { 33610b57cec5SDimitry Andric result += CommentLine; 33620b57cec5SDimitry Andric result += "\n"; 33630b57cec5SDimitry Andric } 33640b57cec5SDimitry Andric result += Imports[Index].Text; 33650b57cec5SDimitry Andric CurrentIsStatic = Imports[Index].IsStatic; 33660b57cec5SDimitry Andric CurrentImportGroup = JavaImportGroups[Index]; 33670b57cec5SDimitry Andric } 33680b57cec5SDimitry Andric 33690b57cec5SDimitry Andric // If the imports are out of order, we generate a single replacement fixing 33700b57cec5SDimitry Andric // the entire block. Otherwise, no replacement is generated. 33715ffd83dbSDimitry Andric if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr( 337281ad6265SDimitry Andric Imports.front().Offset, ImportsBlockSize)))) { 33730b57cec5SDimitry Andric return; 337481ad6265SDimitry Andric } 33750b57cec5SDimitry Andric 33760b57cec5SDimitry Andric auto Err = Replaces.add(tooling::Replacement(FileName, Imports.front().Offset, 33770b57cec5SDimitry Andric ImportsBlockSize, result)); 33780b57cec5SDimitry Andric // FIXME: better error handling. For now, just skip the replacement for the 33790b57cec5SDimitry Andric // release version. 33800b57cec5SDimitry Andric if (Err) { 3381*0fca6ea1SDimitry Andric llvm::errs() << toString(std::move(Err)) << "\n"; 33820b57cec5SDimitry Andric assert(false); 33830b57cec5SDimitry Andric } 33840b57cec5SDimitry Andric } 33850b57cec5SDimitry Andric 33860b57cec5SDimitry Andric namespace { 33870b57cec5SDimitry Andric 33880b57cec5SDimitry Andric const char JavaImportRegexPattern[] = 33890b57cec5SDimitry Andric "^[\t ]*import[\t ]+(static[\t ]*)?([^\t ]*)[\t ]*;"; 33900b57cec5SDimitry Andric 33910b57cec5SDimitry Andric } // anonymous namespace 33920b57cec5SDimitry Andric 33930b57cec5SDimitry Andric tooling::Replacements sortJavaImports(const FormatStyle &Style, StringRef Code, 33940b57cec5SDimitry Andric ArrayRef<tooling::Range> Ranges, 33950b57cec5SDimitry Andric StringRef FileName, 33960b57cec5SDimitry Andric tooling::Replacements &Replaces) { 33970b57cec5SDimitry Andric unsigned Prev = 0; 33980b57cec5SDimitry Andric unsigned SearchFrom = 0; 33990b57cec5SDimitry Andric llvm::Regex ImportRegex(JavaImportRegexPattern); 34000b57cec5SDimitry Andric SmallVector<StringRef, 4> Matches; 34010b57cec5SDimitry Andric SmallVector<JavaImportDirective, 16> ImportsInBlock; 3402753f127fSDimitry Andric SmallVector<StringRef> AssociatedCommentLines; 34030b57cec5SDimitry Andric 34040b57cec5SDimitry Andric bool FormattingOff = false; 34050b57cec5SDimitry Andric 34060b57cec5SDimitry Andric for (;;) { 34070b57cec5SDimitry Andric auto Pos = Code.find('\n', SearchFrom); 34080b57cec5SDimitry Andric StringRef Line = 34090b57cec5SDimitry Andric Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev); 34100b57cec5SDimitry Andric 34110b57cec5SDimitry Andric StringRef Trimmed = Line.trim(); 341206c3fb27SDimitry Andric if (isClangFormatOff(Trimmed)) 34130b57cec5SDimitry Andric FormattingOff = true; 341406c3fb27SDimitry Andric else if (isClangFormatOn(Trimmed)) 34150b57cec5SDimitry Andric FormattingOff = false; 34160b57cec5SDimitry Andric 34170b57cec5SDimitry Andric if (ImportRegex.match(Line, &Matches)) { 34180b57cec5SDimitry Andric if (FormattingOff) { 34190b57cec5SDimitry Andric // If at least one import line has formatting turned off, turn off 34200b57cec5SDimitry Andric // formatting entirely. 34210b57cec5SDimitry Andric return Replaces; 34220b57cec5SDimitry Andric } 34230b57cec5SDimitry Andric StringRef Static = Matches[1]; 34240b57cec5SDimitry Andric StringRef Identifier = Matches[2]; 34250b57cec5SDimitry Andric bool IsStatic = false; 342681ad6265SDimitry Andric if (Static.contains("static")) 34270b57cec5SDimitry Andric IsStatic = true; 34280b57cec5SDimitry Andric ImportsInBlock.push_back( 34290b57cec5SDimitry Andric {Identifier, Line, Prev, AssociatedCommentLines, IsStatic}); 34300b57cec5SDimitry Andric AssociatedCommentLines.clear(); 34310b57cec5SDimitry Andric } else if (Trimmed.size() > 0 && !ImportsInBlock.empty()) { 34320b57cec5SDimitry Andric // Associating comments within the imports with the nearest import below 34330b57cec5SDimitry Andric AssociatedCommentLines.push_back(Line); 34340b57cec5SDimitry Andric } 34350b57cec5SDimitry Andric Prev = Pos + 1; 34360b57cec5SDimitry Andric if (Pos == StringRef::npos || Pos + 1 == Code.size()) 34370b57cec5SDimitry Andric break; 34380b57cec5SDimitry Andric SearchFrom = Pos + 1; 34390b57cec5SDimitry Andric } 34400b57cec5SDimitry Andric if (!ImportsInBlock.empty()) 34410b57cec5SDimitry Andric sortJavaImports(Style, ImportsInBlock, Ranges, FileName, Code, Replaces); 34420b57cec5SDimitry Andric return Replaces; 34430b57cec5SDimitry Andric } 34440b57cec5SDimitry Andric 34450b57cec5SDimitry Andric bool isMpegTS(StringRef Code) { 34460b57cec5SDimitry Andric // MPEG transport streams use the ".ts" file extension. clang-format should 34470b57cec5SDimitry Andric // not attempt to format those. MPEG TS' frame format starts with 0x47 every 34480b57cec5SDimitry Andric // 189 bytes - detect that and return. 34490b57cec5SDimitry Andric return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47; 34500b57cec5SDimitry Andric } 34510b57cec5SDimitry Andric 34525f757f3fSDimitry Andric bool isLikelyXml(StringRef Code) { return Code.ltrim().starts_with("<"); } 34530b57cec5SDimitry Andric 34540b57cec5SDimitry Andric tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code, 34550b57cec5SDimitry Andric ArrayRef<tooling::Range> Ranges, 34560b57cec5SDimitry Andric StringRef FileName, unsigned *Cursor) { 34570b57cec5SDimitry Andric tooling::Replacements Replaces; 3458fe6060f1SDimitry Andric if (!Style.SortIncludes || Style.DisableFormat) 34590b57cec5SDimitry Andric return Replaces; 34600b57cec5SDimitry Andric if (isLikelyXml(Code)) 34610b57cec5SDimitry Andric return Replaces; 34620b57cec5SDimitry Andric if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript && 346381ad6265SDimitry Andric isMpegTS(Code)) { 34640b57cec5SDimitry Andric return Replaces; 346581ad6265SDimitry Andric } 34660b57cec5SDimitry Andric if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript) 34670b57cec5SDimitry Andric return sortJavaScriptImports(Style, Code, Ranges, FileName); 34680b57cec5SDimitry Andric if (Style.Language == FormatStyle::LanguageKind::LK_Java) 34690b57cec5SDimitry Andric return sortJavaImports(Style, Code, Ranges, FileName, Replaces); 34700b57cec5SDimitry Andric sortCppIncludes(Style, Code, Ranges, FileName, Replaces, Cursor); 34710b57cec5SDimitry Andric return Replaces; 34720b57cec5SDimitry Andric } 34730b57cec5SDimitry Andric 34740b57cec5SDimitry Andric template <typename T> 3475*0fca6ea1SDimitry Andric static Expected<tooling::Replacements> 34760b57cec5SDimitry Andric processReplacements(T ProcessFunc, StringRef Code, 34770b57cec5SDimitry Andric const tooling::Replacements &Replaces, 34780b57cec5SDimitry Andric const FormatStyle &Style) { 34790b57cec5SDimitry Andric if (Replaces.empty()) 34800b57cec5SDimitry Andric return tooling::Replacements(); 34810b57cec5SDimitry Andric 34820b57cec5SDimitry Andric auto NewCode = applyAllReplacements(Code, Replaces); 34830b57cec5SDimitry Andric if (!NewCode) 34840b57cec5SDimitry Andric return NewCode.takeError(); 34850b57cec5SDimitry Andric std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges(); 34860b57cec5SDimitry Andric StringRef FileName = Replaces.begin()->getFilePath(); 34870b57cec5SDimitry Andric 34880b57cec5SDimitry Andric tooling::Replacements FormatReplaces = 34890b57cec5SDimitry Andric ProcessFunc(Style, *NewCode, ChangedRanges, FileName); 34900b57cec5SDimitry Andric 34910b57cec5SDimitry Andric return Replaces.merge(FormatReplaces); 34920b57cec5SDimitry Andric } 34930b57cec5SDimitry Andric 3494*0fca6ea1SDimitry Andric Expected<tooling::Replacements> 34950b57cec5SDimitry Andric formatReplacements(StringRef Code, const tooling::Replacements &Replaces, 34960b57cec5SDimitry Andric const FormatStyle &Style) { 34970b57cec5SDimitry Andric // We need to use lambda function here since there are two versions of 34980b57cec5SDimitry Andric // `sortIncludes`. 34990b57cec5SDimitry Andric auto SortIncludes = [](const FormatStyle &Style, StringRef Code, 35000b57cec5SDimitry Andric std::vector<tooling::Range> Ranges, 35010b57cec5SDimitry Andric StringRef FileName) -> tooling::Replacements { 35020b57cec5SDimitry Andric return sortIncludes(Style, Code, Ranges, FileName); 35030b57cec5SDimitry Andric }; 35040b57cec5SDimitry Andric auto SortedReplaces = 35050b57cec5SDimitry Andric processReplacements(SortIncludes, Code, Replaces, Style); 35060b57cec5SDimitry Andric if (!SortedReplaces) 35070b57cec5SDimitry Andric return SortedReplaces.takeError(); 35080b57cec5SDimitry Andric 35090b57cec5SDimitry Andric // We need to use lambda function here since there are two versions of 35100b57cec5SDimitry Andric // `reformat`. 35110b57cec5SDimitry Andric auto Reformat = [](const FormatStyle &Style, StringRef Code, 35120b57cec5SDimitry Andric std::vector<tooling::Range> Ranges, 35130b57cec5SDimitry Andric StringRef FileName) -> tooling::Replacements { 35140b57cec5SDimitry Andric return reformat(Style, Code, Ranges, FileName); 35150b57cec5SDimitry Andric }; 35160b57cec5SDimitry Andric return processReplacements(Reformat, Code, *SortedReplaces, Style); 35170b57cec5SDimitry Andric } 35180b57cec5SDimitry Andric 35190b57cec5SDimitry Andric namespace { 35200b57cec5SDimitry Andric 35210b57cec5SDimitry Andric inline bool isHeaderInsertion(const tooling::Replacement &Replace) { 35220b57cec5SDimitry Andric return Replace.getOffset() == UINT_MAX && Replace.getLength() == 0 && 3523bdd1243dSDimitry Andric tooling::HeaderIncludes::IncludeRegex.match( 3524bdd1243dSDimitry Andric Replace.getReplacementText()); 35250b57cec5SDimitry Andric } 35260b57cec5SDimitry Andric 35270b57cec5SDimitry Andric inline bool isHeaderDeletion(const tooling::Replacement &Replace) { 35280b57cec5SDimitry Andric return Replace.getOffset() == UINT_MAX && Replace.getLength() == 1; 35290b57cec5SDimitry Andric } 35300b57cec5SDimitry Andric 35310b57cec5SDimitry Andric // FIXME: insert empty lines between newly created blocks. 35320b57cec5SDimitry Andric tooling::Replacements 35330b57cec5SDimitry Andric fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces, 35340b57cec5SDimitry Andric const FormatStyle &Style) { 35350b57cec5SDimitry Andric if (!Style.isCpp()) 35360b57cec5SDimitry Andric return Replaces; 35370b57cec5SDimitry Andric 35380b57cec5SDimitry Andric tooling::Replacements HeaderInsertions; 3539*0fca6ea1SDimitry Andric std::set<StringRef> HeadersToDelete; 35400b57cec5SDimitry Andric tooling::Replacements Result; 35410b57cec5SDimitry Andric for (const auto &R : Replaces) { 35420b57cec5SDimitry Andric if (isHeaderInsertion(R)) { 35430b57cec5SDimitry Andric // Replacements from \p Replaces must be conflict-free already, so we can 35440b57cec5SDimitry Andric // simply consume the error. 3545*0fca6ea1SDimitry Andric consumeError(HeaderInsertions.add(R)); 35460b57cec5SDimitry Andric } else if (isHeaderDeletion(R)) { 35470b57cec5SDimitry Andric HeadersToDelete.insert(R.getReplacementText()); 35480b57cec5SDimitry Andric } else if (R.getOffset() == UINT_MAX) { 35490b57cec5SDimitry Andric llvm::errs() << "Insertions other than header #include insertion are " 35500b57cec5SDimitry Andric "not supported! " 35510b57cec5SDimitry Andric << R.getReplacementText() << "\n"; 35520b57cec5SDimitry Andric } else { 3553*0fca6ea1SDimitry Andric consumeError(Result.add(R)); 35540b57cec5SDimitry Andric } 35550b57cec5SDimitry Andric } 35560b57cec5SDimitry Andric if (HeaderInsertions.empty() && HeadersToDelete.empty()) 35570b57cec5SDimitry Andric return Replaces; 35580b57cec5SDimitry Andric 35590b57cec5SDimitry Andric StringRef FileName = Replaces.begin()->getFilePath(); 35600b57cec5SDimitry Andric tooling::HeaderIncludes Includes(FileName, Code, Style.IncludeStyle); 35610b57cec5SDimitry Andric 35620b57cec5SDimitry Andric for (const auto &Header : HeadersToDelete) { 35630b57cec5SDimitry Andric tooling::Replacements Replaces = 35645f757f3fSDimitry Andric Includes.remove(Header.trim("\"<>"), Header.starts_with("<")); 35650b57cec5SDimitry Andric for (const auto &R : Replaces) { 35660b57cec5SDimitry Andric auto Err = Result.add(R); 35670b57cec5SDimitry Andric if (Err) { 35680b57cec5SDimitry Andric // Ignore the deletion on conflict. 35690b57cec5SDimitry Andric llvm::errs() << "Failed to add header deletion replacement for " 3570*0fca6ea1SDimitry Andric << Header << ": " << toString(std::move(Err)) << "\n"; 35710b57cec5SDimitry Andric } 35720b57cec5SDimitry Andric } 35730b57cec5SDimitry Andric } 35740b57cec5SDimitry Andric 3575*0fca6ea1SDimitry Andric SmallVector<StringRef, 4> Matches; 35760b57cec5SDimitry Andric for (const auto &R : HeaderInsertions) { 35770b57cec5SDimitry Andric auto IncludeDirective = R.getReplacementText(); 3578bdd1243dSDimitry Andric bool Matched = 3579bdd1243dSDimitry Andric tooling::HeaderIncludes::IncludeRegex.match(IncludeDirective, &Matches); 35800b57cec5SDimitry Andric assert(Matched && "Header insertion replacement must have replacement text " 35810b57cec5SDimitry Andric "'#include ...'"); 35820b57cec5SDimitry Andric (void)Matched; 35830b57cec5SDimitry Andric auto IncludeName = Matches[2]; 35840b57cec5SDimitry Andric auto Replace = 35855f757f3fSDimitry Andric Includes.insert(IncludeName.trim("\"<>"), IncludeName.starts_with("<"), 3586bdd1243dSDimitry Andric tooling::IncludeDirective::Include); 35870b57cec5SDimitry Andric if (Replace) { 35880b57cec5SDimitry Andric auto Err = Result.add(*Replace); 35890b57cec5SDimitry Andric if (Err) { 3590*0fca6ea1SDimitry Andric consumeError(std::move(Err)); 35910b57cec5SDimitry Andric unsigned NewOffset = 35920b57cec5SDimitry Andric Result.getShiftedCodePosition(Replace->getOffset()); 35930b57cec5SDimitry Andric auto Shifted = tooling::Replacement(FileName, NewOffset, 0, 35940b57cec5SDimitry Andric Replace->getReplacementText()); 35950b57cec5SDimitry Andric Result = Result.merge(tooling::Replacements(Shifted)); 35960b57cec5SDimitry Andric } 35970b57cec5SDimitry Andric } 35980b57cec5SDimitry Andric } 35990b57cec5SDimitry Andric return Result; 36000b57cec5SDimitry Andric } 36010b57cec5SDimitry Andric 36020b57cec5SDimitry Andric } // anonymous namespace 36030b57cec5SDimitry Andric 3604*0fca6ea1SDimitry Andric Expected<tooling::Replacements> 36050b57cec5SDimitry Andric cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces, 36060b57cec5SDimitry Andric const FormatStyle &Style) { 36070b57cec5SDimitry Andric // We need to use lambda function here since there are two versions of 36080b57cec5SDimitry Andric // `cleanup`. 36090b57cec5SDimitry Andric auto Cleanup = [](const FormatStyle &Style, StringRef Code, 3610*0fca6ea1SDimitry Andric ArrayRef<tooling::Range> Ranges, 36110b57cec5SDimitry Andric StringRef FileName) -> tooling::Replacements { 36120b57cec5SDimitry Andric return cleanup(Style, Code, Ranges, FileName); 36130b57cec5SDimitry Andric }; 36140b57cec5SDimitry Andric // Make header insertion replacements insert new headers into correct blocks. 36150b57cec5SDimitry Andric tooling::Replacements NewReplaces = 36160b57cec5SDimitry Andric fixCppIncludeInsertions(Code, Replaces, Style); 3617bdd1243dSDimitry Andric return cantFail(processReplacements(Cleanup, Code, NewReplaces, Style)); 36180b57cec5SDimitry Andric } 36190b57cec5SDimitry Andric 36200b57cec5SDimitry Andric namespace internal { 36210b57cec5SDimitry Andric std::pair<tooling::Replacements, unsigned> 36220b57cec5SDimitry Andric reformat(const FormatStyle &Style, StringRef Code, 36230b57cec5SDimitry Andric ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn, 36240b57cec5SDimitry Andric unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName, 36250b57cec5SDimitry Andric FormattingAttemptStatus *Status) { 3626349cc55cSDimitry Andric FormatStyle Expanded = Style; 3627349cc55cSDimitry Andric expandPresetsBraceWrapping(Expanded); 3628349cc55cSDimitry Andric expandPresetsSpaceBeforeParens(Expanded); 362906c3fb27SDimitry Andric expandPresetsSpacesInParens(Expanded); 3630bdd1243dSDimitry Andric Expanded.InsertBraces = false; 3631bdd1243dSDimitry Andric Expanded.RemoveBracesLLVM = false; 363206c3fb27SDimitry Andric Expanded.RemoveParentheses = FormatStyle::RPS_Leave; 3633bdd1243dSDimitry Andric Expanded.RemoveSemicolon = false; 363481ad6265SDimitry Andric switch (Expanded.RequiresClausePosition) { 363581ad6265SDimitry Andric case FormatStyle::RCPS_SingleLine: 363681ad6265SDimitry Andric case FormatStyle::RCPS_WithPreceding: 363781ad6265SDimitry Andric Expanded.IndentRequiresClause = false; 363881ad6265SDimitry Andric break; 363981ad6265SDimitry Andric default: 364081ad6265SDimitry Andric break; 364181ad6265SDimitry Andric } 364281ad6265SDimitry Andric 36430b57cec5SDimitry Andric if (Expanded.DisableFormat) 36440b57cec5SDimitry Andric return {tooling::Replacements(), 0}; 36450b57cec5SDimitry Andric if (isLikelyXml(Code)) 36460b57cec5SDimitry Andric return {tooling::Replacements(), 0}; 36470b57cec5SDimitry Andric if (Expanded.Language == FormatStyle::LK_JavaScript && isMpegTS(Code)) 36480b57cec5SDimitry Andric return {tooling::Replacements(), 0}; 36490b57cec5SDimitry Andric 3650fe6060f1SDimitry Andric // JSON only needs the formatting passing. 3651fe6060f1SDimitry Andric if (Style.isJson()) { 3652fe6060f1SDimitry Andric std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size())); 36534824e7fdSDimitry Andric auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn, 3654fe6060f1SDimitry Andric NextStartColumn, LastStartColumn); 3655349cc55cSDimitry Andric if (!Env) 3656349cc55cSDimitry Andric return {}; 3657fe6060f1SDimitry Andric // Perform the actual formatting pass. 3658fe6060f1SDimitry Andric tooling::Replacements Replaces = 3659fe6060f1SDimitry Andric Formatter(*Env, Style, Status).process().first; 3660fe6060f1SDimitry Andric // add a replacement to remove the "x = " from the result. 366106c3fb27SDimitry Andric Replaces = Replaces.merge( 366206c3fb27SDimitry Andric tooling::Replacements(tooling::Replacement(FileName, 0, 4, ""))); 3663fe6060f1SDimitry Andric // apply the reformatting changes and the removal of "x = ". 366481ad6265SDimitry Andric if (applyAllReplacements(Code, Replaces)) 3665fe6060f1SDimitry Andric return {Replaces, 0}; 3666fe6060f1SDimitry Andric return {tooling::Replacements(), 0}; 3667fe6060f1SDimitry Andric } 3668fe6060f1SDimitry Andric 3669bdd1243dSDimitry Andric auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn, 3670bdd1243dSDimitry Andric NextStartColumn, LastStartColumn); 3671bdd1243dSDimitry Andric if (!Env) 3672bdd1243dSDimitry Andric return {}; 3673bdd1243dSDimitry Andric 36740b57cec5SDimitry Andric typedef std::function<std::pair<tooling::Replacements, unsigned>( 36750b57cec5SDimitry Andric const Environment &)> 36760b57cec5SDimitry Andric AnalyzerPass; 367706c3fb27SDimitry Andric 367806c3fb27SDimitry Andric SmallVector<AnalyzerPass, 16> Passes; 36790b57cec5SDimitry Andric 3680bdd1243dSDimitry Andric Passes.emplace_back([&](const Environment &Env) { 3681bdd1243dSDimitry Andric return IntegerLiteralSeparatorFixer().process(Env, Expanded); 3682bdd1243dSDimitry Andric }); 3683bdd1243dSDimitry Andric 368481ad6265SDimitry Andric if (Style.isCpp()) { 368506c3fb27SDimitry Andric if (Style.QualifierAlignment != FormatStyle::QAS_Leave) 368606c3fb27SDimitry Andric addQualifierAlignmentFixerPasses(Expanded, Passes); 368706c3fb27SDimitry Andric 368806c3fb27SDimitry Andric if (Style.RemoveParentheses != FormatStyle::RPS_Leave) { 368906c3fb27SDimitry Andric FormatStyle S = Expanded; 369006c3fb27SDimitry Andric S.RemoveParentheses = Style.RemoveParentheses; 369106c3fb27SDimitry Andric Passes.emplace_back([&, S = std::move(S)](const Environment &Env) { 369206c3fb27SDimitry Andric return ParensRemover(Env, S).process(/*SkipAnnotation=*/true); 3693349cc55cSDimitry Andric }); 3694349cc55cSDimitry Andric } 3695349cc55cSDimitry Andric 369681ad6265SDimitry Andric if (Style.InsertBraces) { 3697bdd1243dSDimitry Andric FormatStyle S = Expanded; 3698bdd1243dSDimitry Andric S.InsertBraces = true; 369906c3fb27SDimitry Andric Passes.emplace_back([&, S = std::move(S)](const Environment &Env) { 3700bdd1243dSDimitry Andric return BracesInserter(Env, S).process(/*SkipAnnotation=*/true); 370181ad6265SDimitry Andric }); 370281ad6265SDimitry Andric } 370381ad6265SDimitry Andric 370481ad6265SDimitry Andric if (Style.RemoveBracesLLVM) { 3705bdd1243dSDimitry Andric FormatStyle S = Expanded; 3706bdd1243dSDimitry Andric S.RemoveBracesLLVM = true; 370706c3fb27SDimitry Andric Passes.emplace_back([&, S = std::move(S)](const Environment &Env) { 3708bdd1243dSDimitry Andric return BracesRemover(Env, S).process(/*SkipAnnotation=*/true); 3709bdd1243dSDimitry Andric }); 3710bdd1243dSDimitry Andric } 3711bdd1243dSDimitry Andric 3712bdd1243dSDimitry Andric if (Style.RemoveSemicolon) { 3713bdd1243dSDimitry Andric FormatStyle S = Expanded; 3714bdd1243dSDimitry Andric S.RemoveSemicolon = true; 371506c3fb27SDimitry Andric Passes.emplace_back([&, S = std::move(S)](const Environment &Env) { 3716*0fca6ea1SDimitry Andric return SemiRemover(Env, S).process(); 371704eeddc0SDimitry Andric }); 371881ad6265SDimitry Andric } 371904eeddc0SDimitry Andric 372081ad6265SDimitry Andric if (Style.FixNamespaceComments) { 37210b57cec5SDimitry Andric Passes.emplace_back([&](const Environment &Env) { 37220b57cec5SDimitry Andric return NamespaceEndCommentsFixer(Env, Expanded).process(); 37230b57cec5SDimitry Andric }); 372481ad6265SDimitry Andric } 37250b57cec5SDimitry Andric 3726bdd1243dSDimitry Andric if (Style.SortUsingDeclarations != FormatStyle::SUD_Never) { 37270b57cec5SDimitry Andric Passes.emplace_back([&](const Environment &Env) { 37280b57cec5SDimitry Andric return UsingDeclarationsSorter(Env, Expanded).process(); 37290b57cec5SDimitry Andric }); 37300b57cec5SDimitry Andric } 373181ad6265SDimitry Andric } 37320b57cec5SDimitry Andric 373381ad6265SDimitry Andric if (Style.SeparateDefinitionBlocks != FormatStyle::SDS_Leave) { 373404eeddc0SDimitry Andric Passes.emplace_back([&](const Environment &Env) { 373504eeddc0SDimitry Andric return DefinitionBlockSeparator(Env, Expanded).process(); 373604eeddc0SDimitry Andric }); 373781ad6265SDimitry Andric } 373804eeddc0SDimitry Andric 37395f757f3fSDimitry Andric if (Style.Language == FormatStyle::LK_ObjC && 37405f757f3fSDimitry Andric !Style.ObjCPropertyAttributeOrder.empty()) { 37415f757f3fSDimitry Andric Passes.emplace_back([&](const Environment &Env) { 37425f757f3fSDimitry Andric return ObjCPropertyAttributeOrderFixer(Env, Expanded).process(); 37435f757f3fSDimitry Andric }); 37445f757f3fSDimitry Andric } 37455f757f3fSDimitry Andric 374681ad6265SDimitry Andric if (Style.isJavaScript() && 374781ad6265SDimitry Andric Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) { 37480b57cec5SDimitry Andric Passes.emplace_back([&](const Environment &Env) { 3749bdd1243dSDimitry Andric return JavaScriptRequoter(Env, Expanded).process(/*SkipAnnotation=*/true); 37500b57cec5SDimitry Andric }); 375181ad6265SDimitry Andric } 37520b57cec5SDimitry Andric 37530b57cec5SDimitry Andric Passes.emplace_back([&](const Environment &Env) { 37540b57cec5SDimitry Andric return Formatter(Env, Expanded, Status).process(); 37550b57cec5SDimitry Andric }); 37560b57cec5SDimitry Andric 37570eae32dcSDimitry Andric if (Style.isJavaScript() && 375881ad6265SDimitry Andric Style.InsertTrailingCommas == FormatStyle::TCS_Wrapped) { 37595ffd83dbSDimitry Andric Passes.emplace_back([&](const Environment &Env) { 37605ffd83dbSDimitry Andric return TrailingCommaInserter(Env, Expanded).process(); 37615ffd83dbSDimitry Andric }); 376281ad6265SDimitry Andric } 37635ffd83dbSDimitry Andric 3764bdd1243dSDimitry Andric std::optional<std::string> CurrentCode; 37650b57cec5SDimitry Andric tooling::Replacements Fixes; 37660b57cec5SDimitry Andric unsigned Penalty = 0; 37670b57cec5SDimitry Andric for (size_t I = 0, E = Passes.size(); I < E; ++I) { 37680b57cec5SDimitry Andric std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env); 37690b57cec5SDimitry Andric auto NewCode = applyAllReplacements( 37700b57cec5SDimitry Andric CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first); 37710b57cec5SDimitry Andric if (NewCode) { 37720b57cec5SDimitry Andric Fixes = Fixes.merge(PassFixes.first); 37730b57cec5SDimitry Andric Penalty += PassFixes.second; 37740b57cec5SDimitry Andric if (I + 1 < E) { 37750b57cec5SDimitry Andric CurrentCode = std::move(*NewCode); 3776349cc55cSDimitry Andric Env = Environment::make( 37770b57cec5SDimitry Andric *CurrentCode, FileName, 37780b57cec5SDimitry Andric tooling::calculateRangesAfterReplacements(Fixes, Ranges), 37790b57cec5SDimitry Andric FirstStartColumn, NextStartColumn, LastStartColumn); 3780349cc55cSDimitry Andric if (!Env) 3781349cc55cSDimitry Andric return {}; 37820b57cec5SDimitry Andric } 37830b57cec5SDimitry Andric } 37840b57cec5SDimitry Andric } 37850b57cec5SDimitry Andric 378606c3fb27SDimitry Andric if (Style.QualifierAlignment != FormatStyle::QAS_Leave) { 378706c3fb27SDimitry Andric // Don't make replacements that replace nothing. QualifierAlignment can 378806c3fb27SDimitry Andric // produce them if one of its early passes changes e.g. `const volatile` to 378906c3fb27SDimitry Andric // `volatile const` and then a later pass changes it back again. 379006c3fb27SDimitry Andric tooling::Replacements NonNoOpFixes; 379106c3fb27SDimitry Andric for (const tooling::Replacement &Fix : Fixes) { 379206c3fb27SDimitry Andric StringRef OriginalCode = Code.substr(Fix.getOffset(), Fix.getLength()); 3793*0fca6ea1SDimitry Andric if (OriginalCode != Fix.getReplacementText()) { 379406c3fb27SDimitry Andric auto Err = NonNoOpFixes.add(Fix); 379506c3fb27SDimitry Andric if (Err) { 379606c3fb27SDimitry Andric llvm::errs() << "Error adding replacements : " 3797*0fca6ea1SDimitry Andric << toString(std::move(Err)) << "\n"; 379806c3fb27SDimitry Andric } 379906c3fb27SDimitry Andric } 380006c3fb27SDimitry Andric } 380106c3fb27SDimitry Andric Fixes = std::move(NonNoOpFixes); 380206c3fb27SDimitry Andric } 380306c3fb27SDimitry Andric 38040b57cec5SDimitry Andric return {Fixes, Penalty}; 38050b57cec5SDimitry Andric } 38060b57cec5SDimitry Andric } // namespace internal 38070b57cec5SDimitry Andric 38080b57cec5SDimitry Andric tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, 38090b57cec5SDimitry Andric ArrayRef<tooling::Range> Ranges, 38100b57cec5SDimitry Andric StringRef FileName, 38110b57cec5SDimitry Andric FormattingAttemptStatus *Status) { 38120b57cec5SDimitry Andric return internal::reformat(Style, Code, Ranges, 38130b57cec5SDimitry Andric /*FirstStartColumn=*/0, 38140b57cec5SDimitry Andric /*NextStartColumn=*/0, 38150b57cec5SDimitry Andric /*LastStartColumn=*/0, FileName, Status) 38160b57cec5SDimitry Andric .first; 38170b57cec5SDimitry Andric } 38180b57cec5SDimitry Andric 38190b57cec5SDimitry Andric tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code, 38200b57cec5SDimitry Andric ArrayRef<tooling::Range> Ranges, 38210b57cec5SDimitry Andric StringRef FileName) { 38220b57cec5SDimitry Andric // cleanups only apply to C++ (they mostly concern ctor commas etc.) 38230b57cec5SDimitry Andric if (Style.Language != FormatStyle::LK_Cpp) 38240b57cec5SDimitry Andric return tooling::Replacements(); 3825349cc55cSDimitry Andric auto Env = Environment::make(Code, FileName, Ranges); 3826349cc55cSDimitry Andric if (!Env) 3827349cc55cSDimitry Andric return {}; 3828349cc55cSDimitry Andric return Cleaner(*Env, Style).process().first; 38290b57cec5SDimitry Andric } 38300b57cec5SDimitry Andric 38310b57cec5SDimitry Andric tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, 38320b57cec5SDimitry Andric ArrayRef<tooling::Range> Ranges, 38330b57cec5SDimitry Andric StringRef FileName, bool *IncompleteFormat) { 38340b57cec5SDimitry Andric FormattingAttemptStatus Status; 38350b57cec5SDimitry Andric auto Result = reformat(Style, Code, Ranges, FileName, &Status); 38360b57cec5SDimitry Andric if (!Status.FormatComplete) 38370b57cec5SDimitry Andric *IncompleteFormat = true; 38380b57cec5SDimitry Andric return Result; 38390b57cec5SDimitry Andric } 38400b57cec5SDimitry Andric 38410b57cec5SDimitry Andric tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style, 38420b57cec5SDimitry Andric StringRef Code, 38430b57cec5SDimitry Andric ArrayRef<tooling::Range> Ranges, 38440b57cec5SDimitry Andric StringRef FileName) { 3845349cc55cSDimitry Andric auto Env = Environment::make(Code, FileName, Ranges); 3846349cc55cSDimitry Andric if (!Env) 3847349cc55cSDimitry Andric return {}; 38484824e7fdSDimitry Andric return NamespaceEndCommentsFixer(*Env, Style).process().first; 38490b57cec5SDimitry Andric } 38500b57cec5SDimitry Andric 38510b57cec5SDimitry Andric tooling::Replacements sortUsingDeclarations(const FormatStyle &Style, 38520b57cec5SDimitry Andric StringRef Code, 38530b57cec5SDimitry Andric ArrayRef<tooling::Range> Ranges, 38540b57cec5SDimitry Andric StringRef FileName) { 3855349cc55cSDimitry Andric auto Env = Environment::make(Code, FileName, Ranges); 3856349cc55cSDimitry Andric if (!Env) 3857349cc55cSDimitry Andric return {}; 38584824e7fdSDimitry Andric return UsingDeclarationsSorter(*Env, Style).process().first; 38590b57cec5SDimitry Andric } 38600b57cec5SDimitry Andric 38610b57cec5SDimitry Andric LangOptions getFormattingLangOpts(const FormatStyle &Style) { 38620b57cec5SDimitry Andric LangOptions LangOpts; 3863a7dea167SDimitry Andric 3864a7dea167SDimitry Andric FormatStyle::LanguageStandard LexingStd = Style.Standard; 3865a7dea167SDimitry Andric if (LexingStd == FormatStyle::LS_Auto) 3866a7dea167SDimitry Andric LexingStd = FormatStyle::LS_Latest; 3867a7dea167SDimitry Andric if (LexingStd == FormatStyle::LS_Latest) 3868a7dea167SDimitry Andric LexingStd = FormatStyle::LS_Cpp20; 38690b57cec5SDimitry Andric LangOpts.CPlusPlus = 1; 3870a7dea167SDimitry Andric LangOpts.CPlusPlus11 = LexingStd >= FormatStyle::LS_Cpp11; 3871a7dea167SDimitry Andric LangOpts.CPlusPlus14 = LexingStd >= FormatStyle::LS_Cpp14; 3872a7dea167SDimitry Andric LangOpts.CPlusPlus17 = LexingStd >= FormatStyle::LS_Cpp17; 38735ffd83dbSDimitry Andric LangOpts.CPlusPlus20 = LexingStd >= FormatStyle::LS_Cpp20; 38745ffd83dbSDimitry Andric LangOpts.Char8 = LexingStd >= FormatStyle::LS_Cpp20; 387581ad6265SDimitry Andric // Turning on digraphs in standards before C++0x is error-prone, because e.g. 387681ad6265SDimitry Andric // the sequence "<::" will be unconditionally treated as "[:". 387781ad6265SDimitry Andric // Cf. Lexer::LexTokenInternal. 387881ad6265SDimitry Andric LangOpts.Digraphs = LexingStd >= FormatStyle::LS_Cpp11; 3879a7dea167SDimitry Andric 38800b57cec5SDimitry Andric LangOpts.LineComment = 1; 3881*0fca6ea1SDimitry Andric LangOpts.CXXOperatorNames = Style.isCpp(); 38820b57cec5SDimitry Andric LangOpts.Bool = 1; 38830b57cec5SDimitry Andric LangOpts.ObjC = 1; 38840b57cec5SDimitry Andric LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally. 38850b57cec5SDimitry Andric LangOpts.DeclSpecKeyword = 1; // To get __declspec. 3886e8d8bef9SDimitry Andric LangOpts.C99 = 1; // To get kw_restrict for non-underscore-prefixed restrict. 38870b57cec5SDimitry Andric return LangOpts; 38880b57cec5SDimitry Andric } 38890b57cec5SDimitry Andric 38900b57cec5SDimitry Andric const char *StyleOptionHelpDescription = 3891753f127fSDimitry Andric "Set coding style. <string> can be:\n" 3892753f127fSDimitry Andric "1. A preset: LLVM, GNU, Google, Chromium, Microsoft,\n" 3893753f127fSDimitry Andric " Mozilla, WebKit.\n" 3894753f127fSDimitry Andric "2. 'file' to load style configuration from a\n" 3895753f127fSDimitry Andric " .clang-format file in one of the parent directories\n" 3896753f127fSDimitry Andric " of the source file (for stdin, see --assume-filename).\n" 3897753f127fSDimitry Andric " If no .clang-format file is found, falls back to\n" 3898753f127fSDimitry Andric " --fallback-style.\n" 3899753f127fSDimitry Andric " --style=file is the default.\n" 3900753f127fSDimitry Andric "3. 'file:<format_file_path>' to explicitly specify\n" 390104eeddc0SDimitry Andric " the configuration file.\n" 3902753f127fSDimitry Andric "4. \"{key: value, ...}\" to set specific parameters, e.g.:\n" 3903753f127fSDimitry Andric " --style=\"{BasedOnStyle: llvm, IndentWidth: 8}\""; 39040b57cec5SDimitry Andric 39050b57cec5SDimitry Andric static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) { 39065f757f3fSDimitry Andric if (FileName.ends_with(".java")) 39070b57cec5SDimitry Andric return FormatStyle::LK_Java; 390806c3fb27SDimitry Andric if (FileName.ends_with_insensitive(".js") || 390906c3fb27SDimitry Andric FileName.ends_with_insensitive(".mjs") || 391006c3fb27SDimitry Andric FileName.ends_with_insensitive(".ts")) { 3911a7dea167SDimitry Andric return FormatStyle::LK_JavaScript; // (module) JavaScript or TypeScript. 391281ad6265SDimitry Andric } 39135f757f3fSDimitry Andric if (FileName.ends_with(".m") || FileName.ends_with(".mm")) 39140b57cec5SDimitry Andric return FormatStyle::LK_ObjC; 391506c3fb27SDimitry Andric if (FileName.ends_with_insensitive(".proto") || 391606c3fb27SDimitry Andric FileName.ends_with_insensitive(".protodevel")) { 39170b57cec5SDimitry Andric return FormatStyle::LK_Proto; 391881ad6265SDimitry Andric } 3919*0fca6ea1SDimitry Andric // txtpb is the canonical extension, and textproto is the legacy canonical 3920*0fca6ea1SDimitry Andric // extension 3921*0fca6ea1SDimitry Andric // https://protobuf.dev/reference/protobuf/textformat-spec/#text-format-files 3922*0fca6ea1SDimitry Andric if (FileName.ends_with_insensitive(".txtpb") || 3923*0fca6ea1SDimitry Andric FileName.ends_with_insensitive(".textpb") || 392406c3fb27SDimitry Andric FileName.ends_with_insensitive(".pb.txt") || 392506c3fb27SDimitry Andric FileName.ends_with_insensitive(".textproto") || 392606c3fb27SDimitry Andric FileName.ends_with_insensitive(".asciipb")) { 39270b57cec5SDimitry Andric return FormatStyle::LK_TextProto; 392881ad6265SDimitry Andric } 392906c3fb27SDimitry Andric if (FileName.ends_with_insensitive(".td")) 39300b57cec5SDimitry Andric return FormatStyle::LK_TableGen; 393106c3fb27SDimitry Andric if (FileName.ends_with_insensitive(".cs")) 39320b57cec5SDimitry Andric return FormatStyle::LK_CSharp; 393306c3fb27SDimitry Andric if (FileName.ends_with_insensitive(".json")) 3934fe6060f1SDimitry Andric return FormatStyle::LK_Json; 393506c3fb27SDimitry Andric if (FileName.ends_with_insensitive(".sv") || 393606c3fb27SDimitry Andric FileName.ends_with_insensitive(".svh") || 393706c3fb27SDimitry Andric FileName.ends_with_insensitive(".v") || 393806c3fb27SDimitry Andric FileName.ends_with_insensitive(".vh")) { 393981ad6265SDimitry Andric return FormatStyle::LK_Verilog; 394081ad6265SDimitry Andric } 39410b57cec5SDimitry Andric return FormatStyle::LK_Cpp; 39420b57cec5SDimitry Andric } 39430b57cec5SDimitry Andric 39440b57cec5SDimitry Andric FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) { 39450b57cec5SDimitry Andric const auto GuessedLanguage = getLanguageByFileName(FileName); 39460b57cec5SDimitry Andric if (GuessedLanguage == FormatStyle::LK_Cpp) { 39470b57cec5SDimitry Andric auto Extension = llvm::sys::path::extension(FileName); 39480b57cec5SDimitry Andric // If there's no file extension (or it's .h), we need to check the contents 39490b57cec5SDimitry Andric // of the code to see if it contains Objective-C. 3950*0fca6ea1SDimitry Andric if (!Code.empty() && (Extension.empty() || Extension == ".h")) { 39510b57cec5SDimitry Andric auto NonEmptyFileName = FileName.empty() ? "guess.h" : FileName; 39520b57cec5SDimitry Andric Environment Env(Code, NonEmptyFileName, /*Ranges=*/{}); 39530b57cec5SDimitry Andric ObjCHeaderStyleGuesser Guesser(Env, getLLVMStyle()); 39540b57cec5SDimitry Andric Guesser.process(); 39550b57cec5SDimitry Andric if (Guesser.isObjC()) 39560b57cec5SDimitry Andric return FormatStyle::LK_ObjC; 39570b57cec5SDimitry Andric } 39580b57cec5SDimitry Andric } 39590b57cec5SDimitry Andric return GuessedLanguage; 39600b57cec5SDimitry Andric } 39610b57cec5SDimitry Andric 3962753f127fSDimitry Andric // Update StyleOptionHelpDescription above when changing this. 39630b57cec5SDimitry Andric const char *DefaultFormatStyle = "file"; 39640b57cec5SDimitry Andric 39650b57cec5SDimitry Andric const char *DefaultFallbackStyle = "LLVM"; 39660b57cec5SDimitry Andric 396704eeddc0SDimitry Andric llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> 396804eeddc0SDimitry Andric loadAndParseConfigFile(StringRef ConfigFile, llvm::vfs::FileSystem *FS, 3969*0fca6ea1SDimitry Andric FormatStyle *Style, bool AllowUnknownOptions, 3970*0fca6ea1SDimitry Andric llvm::SourceMgr::DiagHandlerTy DiagHandler) { 397104eeddc0SDimitry Andric llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 397204eeddc0SDimitry Andric FS->getBufferForFile(ConfigFile.str()); 397304eeddc0SDimitry Andric if (auto EC = Text.getError()) 397404eeddc0SDimitry Andric return EC; 3975*0fca6ea1SDimitry Andric if (auto EC = parseConfiguration(*Text.get(), Style, AllowUnknownOptions, 3976*0fca6ea1SDimitry Andric DiagHandler)) { 397704eeddc0SDimitry Andric return EC; 3978*0fca6ea1SDimitry Andric } 397904eeddc0SDimitry Andric return Text; 398004eeddc0SDimitry Andric } 398104eeddc0SDimitry Andric 3982*0fca6ea1SDimitry Andric Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName, 3983*0fca6ea1SDimitry Andric StringRef FallbackStyleName, StringRef Code, 3984*0fca6ea1SDimitry Andric llvm::vfs::FileSystem *FS, 3985*0fca6ea1SDimitry Andric bool AllowUnknownOptions, 3986*0fca6ea1SDimitry Andric llvm::SourceMgr::DiagHandlerTy DiagHandler) { 39870b57cec5SDimitry Andric FormatStyle Style = getLLVMStyle(guessLanguage(FileName, Code)); 39880b57cec5SDimitry Andric FormatStyle FallbackStyle = getNoStyle(); 39890b57cec5SDimitry Andric if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle)) 39905f757f3fSDimitry Andric return make_string_error("Invalid fallback style: " + FallbackStyleName); 39910b57cec5SDimitry Andric 3992*0fca6ea1SDimitry Andric SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 1> ChildFormatTextToApply; 3993fe6060f1SDimitry Andric 39945f757f3fSDimitry Andric if (StyleName.starts_with("{")) { 39950b57cec5SDimitry Andric // Parse YAML/JSON style from the command line. 3996fe6060f1SDimitry Andric StringRef Source = "<command-line>"; 3997fe6060f1SDimitry Andric if (std::error_code ec = 3998fe6060f1SDimitry Andric parseConfiguration(llvm::MemoryBufferRef(StyleName, Source), &Style, 3999*0fca6ea1SDimitry Andric AllowUnknownOptions, DiagHandler)) { 40000b57cec5SDimitry Andric return make_string_error("Error parsing -style: " + ec.message()); 400181ad6265SDimitry Andric } 40025f757f3fSDimitry Andric 40035f757f3fSDimitry Andric if (!Style.InheritsParentConfig) 40045f757f3fSDimitry Andric return Style; 40055f757f3fSDimitry Andric 4006fe6060f1SDimitry Andric ChildFormatTextToApply.emplace_back( 4007fe6060f1SDimitry Andric llvm::MemoryBuffer::getMemBuffer(StyleName, Source, false)); 40080b57cec5SDimitry Andric } 40095f757f3fSDimitry Andric 40105f757f3fSDimitry Andric if (!FS) 40115f757f3fSDimitry Andric FS = llvm::vfs::getRealFileSystem().get(); 40125f757f3fSDimitry Andric assert(FS); 40130b57cec5SDimitry Andric 401404eeddc0SDimitry Andric // User provided clang-format file using -style=file:path/to/format/file. 401504eeddc0SDimitry Andric if (!Style.InheritsParentConfig && 401606c3fb27SDimitry Andric StyleName.starts_with_insensitive("file:")) { 401704eeddc0SDimitry Andric auto ConfigFile = StyleName.substr(5); 401804eeddc0SDimitry Andric llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 4019*0fca6ea1SDimitry Andric loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions, 4020*0fca6ea1SDimitry Andric DiagHandler); 402181ad6265SDimitry Andric if (auto EC = Text.getError()) { 402204eeddc0SDimitry Andric return make_string_error("Error reading " + ConfigFile + ": " + 402304eeddc0SDimitry Andric EC.message()); 402481ad6265SDimitry Andric } 402504eeddc0SDimitry Andric 402604eeddc0SDimitry Andric LLVM_DEBUG(llvm::dbgs() 402704eeddc0SDimitry Andric << "Using configuration file " << ConfigFile << "\n"); 402804eeddc0SDimitry Andric 402904eeddc0SDimitry Andric if (!Style.InheritsParentConfig) 403004eeddc0SDimitry Andric return Style; 403104eeddc0SDimitry Andric 403204eeddc0SDimitry Andric // Search for parent configs starting from the parent directory of 403304eeddc0SDimitry Andric // ConfigFile. 403404eeddc0SDimitry Andric FileName = ConfigFile; 403504eeddc0SDimitry Andric ChildFormatTextToApply.emplace_back(std::move(*Text)); 403604eeddc0SDimitry Andric } 403704eeddc0SDimitry Andric 4038fe6060f1SDimitry Andric // If the style inherits the parent configuration it is a command line 4039fe6060f1SDimitry Andric // configuration, which wants to inherit, so we have to skip the check of the 4040fe6060f1SDimitry Andric // StyleName. 4041fe6060f1SDimitry Andric if (!Style.InheritsParentConfig && !StyleName.equals_insensitive("file")) { 40420b57cec5SDimitry Andric if (!getPredefinedStyle(StyleName, Style.Language, &Style)) 40430b57cec5SDimitry Andric return make_string_error("Invalid value for -style"); 4044fe6060f1SDimitry Andric if (!Style.InheritsParentConfig) 40450b57cec5SDimitry Andric return Style; 40460b57cec5SDimitry Andric } 40470b57cec5SDimitry Andric 40480b57cec5SDimitry Andric SmallString<128> Path(FileName); 40490b57cec5SDimitry Andric if (std::error_code EC = FS->makeAbsolute(Path)) 40500b57cec5SDimitry Andric return make_string_error(EC.message()); 40510b57cec5SDimitry Andric 40525f757f3fSDimitry Andric // Reset possible inheritance 40535f757f3fSDimitry Andric Style.InheritsParentConfig = false; 4054480093f4SDimitry Andric 4055fe6060f1SDimitry Andric auto dropDiagnosticHandler = [](const llvm::SMDiagnostic &, void *) {}; 4056fe6060f1SDimitry Andric 405704eeddc0SDimitry Andric auto applyChildFormatTexts = [&](FormatStyle *Style) { 405804eeddc0SDimitry Andric for (const auto &MemBuf : llvm::reverse(ChildFormatTextToApply)) { 4059*0fca6ea1SDimitry Andric auto EC = 4060*0fca6ea1SDimitry Andric parseConfiguration(*MemBuf, Style, AllowUnknownOptions, 4061*0fca6ea1SDimitry Andric DiagHandler ? DiagHandler : dropDiagnosticHandler); 406204eeddc0SDimitry Andric // It was already correctly parsed. 406304eeddc0SDimitry Andric assert(!EC); 406404eeddc0SDimitry Andric static_cast<void>(EC); 406504eeddc0SDimitry Andric } 406604eeddc0SDimitry Andric }; 406704eeddc0SDimitry Andric 40685f757f3fSDimitry Andric // Look for .clang-format/_clang-format file in the file's parent directories. 4069*0fca6ea1SDimitry Andric SmallVector<std::string, 2> FilesToLookFor; 40705f757f3fSDimitry Andric FilesToLookFor.push_back(".clang-format"); 40715f757f3fSDimitry Andric FilesToLookFor.push_back("_clang-format"); 40725f757f3fSDimitry Andric 40735f757f3fSDimitry Andric SmallString<128> UnsuitableConfigFiles; 40740b57cec5SDimitry Andric for (StringRef Directory = Path; !Directory.empty(); 40750b57cec5SDimitry Andric Directory = llvm::sys::path::parent_path(Directory)) { 40760b57cec5SDimitry Andric auto Status = FS->status(Directory); 40770b57cec5SDimitry Andric if (!Status || 40780b57cec5SDimitry Andric Status->getType() != llvm::sys::fs::file_type::directory_file) { 40790b57cec5SDimitry Andric continue; 40800b57cec5SDimitry Andric } 40810b57cec5SDimitry Andric 4082480093f4SDimitry Andric for (const auto &F : FilesToLookFor) { 40830b57cec5SDimitry Andric SmallString<128> ConfigFile(Directory); 40840b57cec5SDimitry Andric 4085480093f4SDimitry Andric llvm::sys::path::append(ConfigFile, F); 40860b57cec5SDimitry Andric LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n"); 40870b57cec5SDimitry Andric 40885f757f3fSDimitry Andric Status = FS->status(ConfigFile); 40895f757f3fSDimitry Andric if (!Status || 40905f757f3fSDimitry Andric Status->getType() != llvm::sys::fs::file_type::regular_file) { 40915f757f3fSDimitry Andric continue; 40925f757f3fSDimitry Andric } 40930b57cec5SDimitry Andric 40940b57cec5SDimitry Andric llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 4095*0fca6ea1SDimitry Andric loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions, 4096*0fca6ea1SDimitry Andric DiagHandler); 409704eeddc0SDimitry Andric if (auto EC = Text.getError()) { 40985f757f3fSDimitry Andric if (EC != ParseError::Unsuitable) { 40995f757f3fSDimitry Andric return make_string_error("Error reading " + ConfigFile + ": " + 41005f757f3fSDimitry Andric EC.message()); 41015f757f3fSDimitry Andric } 41020b57cec5SDimitry Andric if (!UnsuitableConfigFiles.empty()) 41030b57cec5SDimitry Andric UnsuitableConfigFiles.append(", "); 41040b57cec5SDimitry Andric UnsuitableConfigFiles.append(ConfigFile); 41050b57cec5SDimitry Andric continue; 41060b57cec5SDimitry Andric } 41075f757f3fSDimitry Andric 41080b57cec5SDimitry Andric LLVM_DEBUG(llvm::dbgs() 41090b57cec5SDimitry Andric << "Using configuration file " << ConfigFile << "\n"); 4110fe6060f1SDimitry Andric 4111fe6060f1SDimitry Andric if (!Style.InheritsParentConfig) { 41125f757f3fSDimitry Andric if (!ChildFormatTextToApply.empty()) { 4113fe6060f1SDimitry Andric LLVM_DEBUG(llvm::dbgs() << "Applying child configurations\n"); 411404eeddc0SDimitry Andric applyChildFormatTexts(&Style); 41155f757f3fSDimitry Andric } 4116fe6060f1SDimitry Andric return Style; 4117fe6060f1SDimitry Andric } 4118fe6060f1SDimitry Andric 4119fe6060f1SDimitry Andric LLVM_DEBUG(llvm::dbgs() << "Inherits parent configuration\n"); 4120fe6060f1SDimitry Andric 4121fe6060f1SDimitry Andric // Reset inheritance of style 4122fe6060f1SDimitry Andric Style.InheritsParentConfig = false; 4123fe6060f1SDimitry Andric 4124fe6060f1SDimitry Andric ChildFormatTextToApply.emplace_back(std::move(*Text)); 4125fe6060f1SDimitry Andric 4126fe6060f1SDimitry Andric // Breaking out of the inner loop, since we don't want to parse 4127fe6060f1SDimitry Andric // .clang-format AND _clang-format, if both exist. Then we continue the 41285f757f3fSDimitry Andric // outer loop (parent directories) in search for the parent 4129fe6060f1SDimitry Andric // configuration. 4130fe6060f1SDimitry Andric break; 41310b57cec5SDimitry Andric } 41320b57cec5SDimitry Andric } 41335f757f3fSDimitry Andric 413481ad6265SDimitry Andric if (!UnsuitableConfigFiles.empty()) { 41350b57cec5SDimitry Andric return make_string_error("Configuration file(s) do(es) not support " + 41360b57cec5SDimitry Andric getLanguageName(Style.Language) + ": " + 41370b57cec5SDimitry Andric UnsuitableConfigFiles); 413881ad6265SDimitry Andric } 4139fe6060f1SDimitry Andric 4140fe6060f1SDimitry Andric if (!ChildFormatTextToApply.empty()) { 4141fe6060f1SDimitry Andric LLVM_DEBUG(llvm::dbgs() 414204eeddc0SDimitry Andric << "Applying child configurations on fallback style\n"); 414304eeddc0SDimitry Andric applyChildFormatTexts(&FallbackStyle); 4144fe6060f1SDimitry Andric } 4145fe6060f1SDimitry Andric 41460b57cec5SDimitry Andric return FallbackStyle; 41470b57cec5SDimitry Andric } 41480b57cec5SDimitry Andric 414906c3fb27SDimitry Andric static bool isClangFormatOnOff(StringRef Comment, bool On) { 415006c3fb27SDimitry Andric if (Comment == (On ? "/* clang-format on */" : "/* clang-format off */")) 415106c3fb27SDimitry Andric return true; 415206c3fb27SDimitry Andric 415306c3fb27SDimitry Andric static const char ClangFormatOn[] = "// clang-format on"; 415406c3fb27SDimitry Andric static const char ClangFormatOff[] = "// clang-format off"; 415506c3fb27SDimitry Andric const unsigned Size = (On ? sizeof ClangFormatOn : sizeof ClangFormatOff) - 1; 415606c3fb27SDimitry Andric 41575f757f3fSDimitry Andric return Comment.starts_with(On ? ClangFormatOn : ClangFormatOff) && 415806c3fb27SDimitry Andric (Comment.size() == Size || Comment[Size] == ':'); 415906c3fb27SDimitry Andric } 416006c3fb27SDimitry Andric 416106c3fb27SDimitry Andric bool isClangFormatOn(StringRef Comment) { 416206c3fb27SDimitry Andric return isClangFormatOnOff(Comment, /*On=*/true); 416306c3fb27SDimitry Andric } 416406c3fb27SDimitry Andric 416506c3fb27SDimitry Andric bool isClangFormatOff(StringRef Comment) { 416606c3fb27SDimitry Andric return isClangFormatOnOff(Comment, /*On=*/false); 416706c3fb27SDimitry Andric } 416806c3fb27SDimitry Andric 41690b57cec5SDimitry Andric } // namespace format 41700b57cec5SDimitry Andric } // namespace clang 4171