Path: blob/main/contrib/llvm-project/clang/lib/Format/Format.cpp
35232 views
//===--- Format.cpp - Format C++ code -------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7///8/// \file9/// This file implements functions declared in Format.h. This will be10/// split into separate files as we go.11///12//===----------------------------------------------------------------------===//1314#include "clang/Format/Format.h"15#include "DefinitionBlockSeparator.h"16#include "IntegerLiteralSeparatorFixer.h"17#include "NamespaceEndCommentsFixer.h"18#include "ObjCPropertyAttributeOrderFixer.h"19#include "QualifierAlignmentFixer.h"20#include "SortJavaScriptImports.h"21#include "UnwrappedLineFormatter.h"22#include "UsingDeclarationsSorter.h"23#include "clang/Tooling/Inclusions/HeaderIncludes.h"24#include "llvm/ADT/Sequence.h"2526#define DEBUG_TYPE "format-formatter"2728using clang::format::FormatStyle;2930LLVM_YAML_IS_SEQUENCE_VECTOR(FormatStyle::RawStringFormat)3132namespace llvm {33namespace yaml {34template <>35struct ScalarEnumerationTraits<FormatStyle::BreakBeforeNoexceptSpecifierStyle> {36static void37enumeration(IO &IO, FormatStyle::BreakBeforeNoexceptSpecifierStyle &Value) {38IO.enumCase(Value, "Never", FormatStyle::BBNSS_Never);39IO.enumCase(Value, "OnlyWithParen", FormatStyle::BBNSS_OnlyWithParen);40IO.enumCase(Value, "Always", FormatStyle::BBNSS_Always);41}42};4344template <> struct MappingTraits<FormatStyle::AlignConsecutiveStyle> {45static void enumInput(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {46IO.enumCase(Value, "None",47FormatStyle::AlignConsecutiveStyle(48{/*Enabled=*/false, /*AcrossEmptyLines=*/false,49/*AcrossComments=*/false, /*AlignCompound=*/false,50/*AlignFunctionPointers=*/false, /*PadOperators=*/true}));51IO.enumCase(Value, "Consecutive",52FormatStyle::AlignConsecutiveStyle(53{/*Enabled=*/true, /*AcrossEmptyLines=*/false,54/*AcrossComments=*/false, /*AlignCompound=*/false,55/*AlignFunctionPointers=*/false, /*PadOperators=*/true}));56IO.enumCase(Value, "AcrossEmptyLines",57FormatStyle::AlignConsecutiveStyle(58{/*Enabled=*/true, /*AcrossEmptyLines=*/true,59/*AcrossComments=*/false, /*AlignCompound=*/false,60/*AlignFunctionPointers=*/false, /*PadOperators=*/true}));61IO.enumCase(Value, "AcrossComments",62FormatStyle::AlignConsecutiveStyle(63{/*Enabled=*/true, /*AcrossEmptyLines=*/false,64/*AcrossComments=*/true, /*AlignCompound=*/false,65/*AlignFunctionPointers=*/false, /*PadOperators=*/true}));66IO.enumCase(Value, "AcrossEmptyLinesAndComments",67FormatStyle::AlignConsecutiveStyle(68{/*Enabled=*/true, /*AcrossEmptyLines=*/true,69/*AcrossComments=*/true, /*AlignCompound=*/false,70/*AlignFunctionPointers=*/false, /*PadOperators=*/true}));7172// For backward compatibility.73IO.enumCase(Value, "true",74FormatStyle::AlignConsecutiveStyle(75{/*Enabled=*/true, /*AcrossEmptyLines=*/false,76/*AcrossComments=*/false, /*AlignCompound=*/false,77/*AlignFunctionPointers=*/false, /*PadOperators=*/true}));78IO.enumCase(Value, "false",79FormatStyle::AlignConsecutiveStyle(80{/*Enabled=*/false, /*AcrossEmptyLines=*/false,81/*AcrossComments=*/false, /*AlignCompound=*/false,82/*AlignFunctionPointers=*/false, /*PadOperators=*/true}));83}8485static void mapping(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {86IO.mapOptional("Enabled", Value.Enabled);87IO.mapOptional("AcrossEmptyLines", Value.AcrossEmptyLines);88IO.mapOptional("AcrossComments", Value.AcrossComments);89IO.mapOptional("AlignCompound", Value.AlignCompound);90IO.mapOptional("AlignFunctionPointers", Value.AlignFunctionPointers);91IO.mapOptional("PadOperators", Value.PadOperators);92}93};9495template <>96struct MappingTraits<FormatStyle::ShortCaseStatementsAlignmentStyle> {97static void mapping(IO &IO,98FormatStyle::ShortCaseStatementsAlignmentStyle &Value) {99IO.mapOptional("Enabled", Value.Enabled);100IO.mapOptional("AcrossEmptyLines", Value.AcrossEmptyLines);101IO.mapOptional("AcrossComments", Value.AcrossComments);102IO.mapOptional("AlignCaseArrows", Value.AlignCaseArrows);103IO.mapOptional("AlignCaseColons", Value.AlignCaseColons);104}105};106107template <>108struct ScalarEnumerationTraits<FormatStyle::AttributeBreakingStyle> {109static void enumeration(IO &IO, FormatStyle::AttributeBreakingStyle &Value) {110IO.enumCase(Value, "Always", FormatStyle::ABS_Always);111IO.enumCase(Value, "Leave", FormatStyle::ABS_Leave);112IO.enumCase(Value, "Never", FormatStyle::ABS_Never);113}114};115116template <>117struct ScalarEnumerationTraits<FormatStyle::ArrayInitializerAlignmentStyle> {118static void enumeration(IO &IO,119FormatStyle::ArrayInitializerAlignmentStyle &Value) {120IO.enumCase(Value, "None", FormatStyle::AIAS_None);121IO.enumCase(Value, "Left", FormatStyle::AIAS_Left);122IO.enumCase(Value, "Right", FormatStyle::AIAS_Right);123}124};125126template <> struct ScalarEnumerationTraits<FormatStyle::BinaryOperatorStyle> {127static void enumeration(IO &IO, FormatStyle::BinaryOperatorStyle &Value) {128IO.enumCase(Value, "All", FormatStyle::BOS_All);129IO.enumCase(Value, "true", FormatStyle::BOS_All);130IO.enumCase(Value, "None", FormatStyle::BOS_None);131IO.enumCase(Value, "false", FormatStyle::BOS_None);132IO.enumCase(Value, "NonAssignment", FormatStyle::BOS_NonAssignment);133}134};135136template <> struct ScalarEnumerationTraits<FormatStyle::BinPackStyle> {137static void enumeration(IO &IO, FormatStyle::BinPackStyle &Value) {138IO.enumCase(Value, "Auto", FormatStyle::BPS_Auto);139IO.enumCase(Value, "Always", FormatStyle::BPS_Always);140IO.enumCase(Value, "Never", FormatStyle::BPS_Never);141}142};143144template <>145struct ScalarEnumerationTraits<FormatStyle::BitFieldColonSpacingStyle> {146static void enumeration(IO &IO,147FormatStyle::BitFieldColonSpacingStyle &Value) {148IO.enumCase(Value, "Both", FormatStyle::BFCS_Both);149IO.enumCase(Value, "None", FormatStyle::BFCS_None);150IO.enumCase(Value, "Before", FormatStyle::BFCS_Before);151IO.enumCase(Value, "After", FormatStyle::BFCS_After);152}153};154155template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> {156static void enumeration(IO &IO, FormatStyle::BraceBreakingStyle &Value) {157IO.enumCase(Value, "Attach", FormatStyle::BS_Attach);158IO.enumCase(Value, "Linux", FormatStyle::BS_Linux);159IO.enumCase(Value, "Mozilla", FormatStyle::BS_Mozilla);160IO.enumCase(Value, "Stroustrup", FormatStyle::BS_Stroustrup);161IO.enumCase(Value, "Allman", FormatStyle::BS_Allman);162IO.enumCase(Value, "Whitesmiths", FormatStyle::BS_Whitesmiths);163IO.enumCase(Value, "GNU", FormatStyle::BS_GNU);164IO.enumCase(Value, "WebKit", FormatStyle::BS_WebKit);165IO.enumCase(Value, "Custom", FormatStyle::BS_Custom);166}167};168169template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> {170static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping) {171IO.mapOptional("AfterCaseLabel", Wrapping.AfterCaseLabel);172IO.mapOptional("AfterClass", Wrapping.AfterClass);173IO.mapOptional("AfterControlStatement", Wrapping.AfterControlStatement);174IO.mapOptional("AfterEnum", Wrapping.AfterEnum);175IO.mapOptional("AfterExternBlock", Wrapping.AfterExternBlock);176IO.mapOptional("AfterFunction", Wrapping.AfterFunction);177IO.mapOptional("AfterNamespace", Wrapping.AfterNamespace);178IO.mapOptional("AfterObjCDeclaration", Wrapping.AfterObjCDeclaration);179IO.mapOptional("AfterStruct", Wrapping.AfterStruct);180IO.mapOptional("AfterUnion", Wrapping.AfterUnion);181IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch);182IO.mapOptional("BeforeElse", Wrapping.BeforeElse);183IO.mapOptional("BeforeLambdaBody", Wrapping.BeforeLambdaBody);184IO.mapOptional("BeforeWhile", Wrapping.BeforeWhile);185IO.mapOptional("IndentBraces", Wrapping.IndentBraces);186IO.mapOptional("SplitEmptyFunction", Wrapping.SplitEmptyFunction);187IO.mapOptional("SplitEmptyRecord", Wrapping.SplitEmptyRecord);188IO.mapOptional("SplitEmptyNamespace", Wrapping.SplitEmptyNamespace);189}190};191192template <> struct ScalarEnumerationTraits<FormatStyle::BracketAlignmentStyle> {193static void enumeration(IO &IO, FormatStyle::BracketAlignmentStyle &Value) {194IO.enumCase(Value, "Align", FormatStyle::BAS_Align);195IO.enumCase(Value, "DontAlign", FormatStyle::BAS_DontAlign);196IO.enumCase(Value, "AlwaysBreak", FormatStyle::BAS_AlwaysBreak);197IO.enumCase(Value, "BlockIndent", FormatStyle::BAS_BlockIndent);198199// For backward compatibility.200IO.enumCase(Value, "true", FormatStyle::BAS_Align);201IO.enumCase(Value, "false", FormatStyle::BAS_DontAlign);202}203};204205template <>206struct ScalarEnumerationTraits<207FormatStyle::BraceWrappingAfterControlStatementStyle> {208static void209enumeration(IO &IO,210FormatStyle::BraceWrappingAfterControlStatementStyle &Value) {211IO.enumCase(Value, "Never", FormatStyle::BWACS_Never);212IO.enumCase(Value, "MultiLine", FormatStyle::BWACS_MultiLine);213IO.enumCase(Value, "Always", FormatStyle::BWACS_Always);214215// For backward compatibility.216IO.enumCase(Value, "false", FormatStyle::BWACS_Never);217IO.enumCase(Value, "true", FormatStyle::BWACS_Always);218}219};220221template <>222struct ScalarEnumerationTraits<223FormatStyle::BreakBeforeConceptDeclarationsStyle> {224static void225enumeration(IO &IO, FormatStyle::BreakBeforeConceptDeclarationsStyle &Value) {226IO.enumCase(Value, "Never", FormatStyle::BBCDS_Never);227IO.enumCase(Value, "Allowed", FormatStyle::BBCDS_Allowed);228IO.enumCase(Value, "Always", FormatStyle::BBCDS_Always);229230// For backward compatibility.231IO.enumCase(Value, "true", FormatStyle::BBCDS_Always);232IO.enumCase(Value, "false", FormatStyle::BBCDS_Allowed);233}234};235236template <>237struct ScalarEnumerationTraits<FormatStyle::BreakBeforeInlineASMColonStyle> {238static void enumeration(IO &IO,239FormatStyle::BreakBeforeInlineASMColonStyle &Value) {240IO.enumCase(Value, "Never", FormatStyle::BBIAS_Never);241IO.enumCase(Value, "OnlyMultiline", FormatStyle::BBIAS_OnlyMultiline);242IO.enumCase(Value, "Always", FormatStyle::BBIAS_Always);243}244};245246template <>247struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> {248static void249enumeration(IO &IO, FormatStyle::BreakConstructorInitializersStyle &Value) {250IO.enumCase(Value, "BeforeColon", FormatStyle::BCIS_BeforeColon);251IO.enumCase(Value, "BeforeComma", FormatStyle::BCIS_BeforeComma);252IO.enumCase(Value, "AfterColon", FormatStyle::BCIS_AfterColon);253}254};255256template <>257struct ScalarEnumerationTraits<FormatStyle::BreakInheritanceListStyle> {258static void enumeration(IO &IO,259FormatStyle::BreakInheritanceListStyle &Value) {260IO.enumCase(Value, "BeforeColon", FormatStyle::BILS_BeforeColon);261IO.enumCase(Value, "BeforeComma", FormatStyle::BILS_BeforeComma);262IO.enumCase(Value, "AfterColon", FormatStyle::BILS_AfterColon);263IO.enumCase(Value, "AfterComma", FormatStyle::BILS_AfterComma);264}265};266267template <>268struct ScalarEnumerationTraits<FormatStyle::BreakTemplateDeclarationsStyle> {269static void enumeration(IO &IO,270FormatStyle::BreakTemplateDeclarationsStyle &Value) {271IO.enumCase(Value, "Leave", FormatStyle::BTDS_Leave);272IO.enumCase(Value, "No", FormatStyle::BTDS_No);273IO.enumCase(Value, "MultiLine", FormatStyle::BTDS_MultiLine);274IO.enumCase(Value, "Yes", FormatStyle::BTDS_Yes);275276// For backward compatibility.277IO.enumCase(Value, "false", FormatStyle::BTDS_MultiLine);278IO.enumCase(Value, "true", FormatStyle::BTDS_Yes);279}280};281282template <> struct ScalarEnumerationTraits<FormatStyle::DAGArgStyle> {283static void enumeration(IO &IO, FormatStyle::DAGArgStyle &Value) {284IO.enumCase(Value, "DontBreak", FormatStyle::DAS_DontBreak);285IO.enumCase(Value, "BreakElements", FormatStyle::DAS_BreakElements);286IO.enumCase(Value, "BreakAll", FormatStyle::DAS_BreakAll);287}288};289290template <>291struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> {292static void293enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) {294IO.enumCase(Value, "None", FormatStyle::DRTBS_None);295IO.enumCase(Value, "All", FormatStyle::DRTBS_All);296IO.enumCase(Value, "TopLevel", FormatStyle::DRTBS_TopLevel);297298// For backward compatibility.299IO.enumCase(Value, "false", FormatStyle::DRTBS_None);300IO.enumCase(Value, "true", FormatStyle::DRTBS_All);301}302};303304template <>305struct ScalarEnumerationTraits<FormatStyle::EscapedNewlineAlignmentStyle> {306static void enumeration(IO &IO,307FormatStyle::EscapedNewlineAlignmentStyle &Value) {308IO.enumCase(Value, "DontAlign", FormatStyle::ENAS_DontAlign);309IO.enumCase(Value, "Left", FormatStyle::ENAS_Left);310IO.enumCase(Value, "LeftWithLastLine", FormatStyle::ENAS_LeftWithLastLine);311IO.enumCase(Value, "Right", FormatStyle::ENAS_Right);312313// For backward compatibility.314IO.enumCase(Value, "true", FormatStyle::ENAS_Left);315IO.enumCase(Value, "false", FormatStyle::ENAS_Right);316}317};318319template <>320struct ScalarEnumerationTraits<FormatStyle::EmptyLineAfterAccessModifierStyle> {321static void322enumeration(IO &IO, FormatStyle::EmptyLineAfterAccessModifierStyle &Value) {323IO.enumCase(Value, "Never", FormatStyle::ELAAMS_Never);324IO.enumCase(Value, "Leave", FormatStyle::ELAAMS_Leave);325IO.enumCase(Value, "Always", FormatStyle::ELAAMS_Always);326}327};328329template <>330struct ScalarEnumerationTraits<331FormatStyle::EmptyLineBeforeAccessModifierStyle> {332static void333enumeration(IO &IO, FormatStyle::EmptyLineBeforeAccessModifierStyle &Value) {334IO.enumCase(Value, "Never", FormatStyle::ELBAMS_Never);335IO.enumCase(Value, "Leave", FormatStyle::ELBAMS_Leave);336IO.enumCase(Value, "LogicalBlock", FormatStyle::ELBAMS_LogicalBlock);337IO.enumCase(Value, "Always", FormatStyle::ELBAMS_Always);338}339};340341template <>342struct ScalarEnumerationTraits<FormatStyle::IndentExternBlockStyle> {343static void enumeration(IO &IO, FormatStyle::IndentExternBlockStyle &Value) {344IO.enumCase(Value, "AfterExternBlock", FormatStyle::IEBS_AfterExternBlock);345IO.enumCase(Value, "Indent", FormatStyle::IEBS_Indent);346IO.enumCase(Value, "NoIndent", FormatStyle::IEBS_NoIndent);347IO.enumCase(Value, "true", FormatStyle::IEBS_Indent);348IO.enumCase(Value, "false", FormatStyle::IEBS_NoIndent);349}350};351352template <> struct MappingTraits<FormatStyle::IntegerLiteralSeparatorStyle> {353static void mapping(IO &IO, FormatStyle::IntegerLiteralSeparatorStyle &Base) {354IO.mapOptional("Binary", Base.Binary);355IO.mapOptional("BinaryMinDigits", Base.BinaryMinDigits);356IO.mapOptional("Decimal", Base.Decimal);357IO.mapOptional("DecimalMinDigits", Base.DecimalMinDigits);358IO.mapOptional("Hex", Base.Hex);359IO.mapOptional("HexMinDigits", Base.HexMinDigits);360}361};362363template <> struct ScalarEnumerationTraits<FormatStyle::JavaScriptQuoteStyle> {364static void enumeration(IO &IO, FormatStyle::JavaScriptQuoteStyle &Value) {365IO.enumCase(Value, "Leave", FormatStyle::JSQS_Leave);366IO.enumCase(Value, "Single", FormatStyle::JSQS_Single);367IO.enumCase(Value, "Double", FormatStyle::JSQS_Double);368}369};370371template <> struct MappingTraits<FormatStyle::KeepEmptyLinesStyle> {372static void mapping(IO &IO, FormatStyle::KeepEmptyLinesStyle &Value) {373IO.mapOptional("AtEndOfFile", Value.AtEndOfFile);374IO.mapOptional("AtStartOfBlock", Value.AtStartOfBlock);375IO.mapOptional("AtStartOfFile", Value.AtStartOfFile);376}377};378379template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> {380static void enumeration(IO &IO, FormatStyle::LanguageKind &Value) {381IO.enumCase(Value, "Cpp", FormatStyle::LK_Cpp);382IO.enumCase(Value, "Java", FormatStyle::LK_Java);383IO.enumCase(Value, "JavaScript", FormatStyle::LK_JavaScript);384IO.enumCase(Value, "ObjC", FormatStyle::LK_ObjC);385IO.enumCase(Value, "Proto", FormatStyle::LK_Proto);386IO.enumCase(Value, "TableGen", FormatStyle::LK_TableGen);387IO.enumCase(Value, "TextProto", FormatStyle::LK_TextProto);388IO.enumCase(Value, "CSharp", FormatStyle::LK_CSharp);389IO.enumCase(Value, "Json", FormatStyle::LK_Json);390IO.enumCase(Value, "Verilog", FormatStyle::LK_Verilog);391}392};393394template <> struct ScalarEnumerationTraits<FormatStyle::LanguageStandard> {395static void enumeration(IO &IO, FormatStyle::LanguageStandard &Value) {396IO.enumCase(Value, "c++03", FormatStyle::LS_Cpp03);397IO.enumCase(Value, "C++03", FormatStyle::LS_Cpp03); // Legacy alias398IO.enumCase(Value, "Cpp03", FormatStyle::LS_Cpp03); // Legacy alias399400IO.enumCase(Value, "c++11", FormatStyle::LS_Cpp11);401IO.enumCase(Value, "C++11", FormatStyle::LS_Cpp11); // Legacy alias402403IO.enumCase(Value, "c++14", FormatStyle::LS_Cpp14);404IO.enumCase(Value, "c++17", FormatStyle::LS_Cpp17);405IO.enumCase(Value, "c++20", FormatStyle::LS_Cpp20);406407IO.enumCase(Value, "Latest", FormatStyle::LS_Latest);408IO.enumCase(Value, "Cpp11", FormatStyle::LS_Latest); // Legacy alias409IO.enumCase(Value, "Auto", FormatStyle::LS_Auto);410}411};412413template <>414struct ScalarEnumerationTraits<FormatStyle::LambdaBodyIndentationKind> {415static void enumeration(IO &IO,416FormatStyle::LambdaBodyIndentationKind &Value) {417IO.enumCase(Value, "Signature", FormatStyle::LBI_Signature);418IO.enumCase(Value, "OuterScope", FormatStyle::LBI_OuterScope);419}420};421422template <> struct ScalarEnumerationTraits<FormatStyle::LineEndingStyle> {423static void enumeration(IO &IO, FormatStyle::LineEndingStyle &Value) {424IO.enumCase(Value, "LF", FormatStyle::LE_LF);425IO.enumCase(Value, "CRLF", FormatStyle::LE_CRLF);426IO.enumCase(Value, "DeriveLF", FormatStyle::LE_DeriveLF);427IO.enumCase(Value, "DeriveCRLF", FormatStyle::LE_DeriveCRLF);428}429};430431template <>432struct ScalarEnumerationTraits<FormatStyle::NamespaceIndentationKind> {433static void enumeration(IO &IO,434FormatStyle::NamespaceIndentationKind &Value) {435IO.enumCase(Value, "None", FormatStyle::NI_None);436IO.enumCase(Value, "Inner", FormatStyle::NI_Inner);437IO.enumCase(Value, "All", FormatStyle::NI_All);438}439};440441template <> struct ScalarEnumerationTraits<FormatStyle::OperandAlignmentStyle> {442static void enumeration(IO &IO, FormatStyle::OperandAlignmentStyle &Value) {443IO.enumCase(Value, "DontAlign", FormatStyle::OAS_DontAlign);444IO.enumCase(Value, "Align", FormatStyle::OAS_Align);445IO.enumCase(Value, "AlignAfterOperator",446FormatStyle::OAS_AlignAfterOperator);447448// For backward compatibility.449IO.enumCase(Value, "true", FormatStyle::OAS_Align);450IO.enumCase(Value, "false", FormatStyle::OAS_DontAlign);451}452};453454template <>455struct ScalarEnumerationTraits<FormatStyle::PackConstructorInitializersStyle> {456static void457enumeration(IO &IO, FormatStyle::PackConstructorInitializersStyle &Value) {458IO.enumCase(Value, "Never", FormatStyle::PCIS_Never);459IO.enumCase(Value, "BinPack", FormatStyle::PCIS_BinPack);460IO.enumCase(Value, "CurrentLine", FormatStyle::PCIS_CurrentLine);461IO.enumCase(Value, "NextLine", FormatStyle::PCIS_NextLine);462IO.enumCase(Value, "NextLineOnly", FormatStyle::PCIS_NextLineOnly);463}464};465466template <> struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {467static void enumeration(IO &IO, FormatStyle::PointerAlignmentStyle &Value) {468IO.enumCase(Value, "Middle", FormatStyle::PAS_Middle);469IO.enumCase(Value, "Left", FormatStyle::PAS_Left);470IO.enumCase(Value, "Right", FormatStyle::PAS_Right);471472// For backward compatibility.473IO.enumCase(Value, "true", FormatStyle::PAS_Left);474IO.enumCase(Value, "false", FormatStyle::PAS_Right);475}476};477478template <>479struct ScalarEnumerationTraits<FormatStyle::PPDirectiveIndentStyle> {480static void enumeration(IO &IO, FormatStyle::PPDirectiveIndentStyle &Value) {481IO.enumCase(Value, "None", FormatStyle::PPDIS_None);482IO.enumCase(Value, "AfterHash", FormatStyle::PPDIS_AfterHash);483IO.enumCase(Value, "BeforeHash", FormatStyle::PPDIS_BeforeHash);484}485};486487template <>488struct ScalarEnumerationTraits<FormatStyle::QualifierAlignmentStyle> {489static void enumeration(IO &IO, FormatStyle::QualifierAlignmentStyle &Value) {490IO.enumCase(Value, "Leave", FormatStyle::QAS_Leave);491IO.enumCase(Value, "Left", FormatStyle::QAS_Left);492IO.enumCase(Value, "Right", FormatStyle::QAS_Right);493IO.enumCase(Value, "Custom", FormatStyle::QAS_Custom);494}495};496497template <> struct MappingTraits<FormatStyle::RawStringFormat> {498static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) {499IO.mapOptional("Language", Format.Language);500IO.mapOptional("Delimiters", Format.Delimiters);501IO.mapOptional("EnclosingFunctions", Format.EnclosingFunctions);502IO.mapOptional("CanonicalDelimiter", Format.CanonicalDelimiter);503IO.mapOptional("BasedOnStyle", Format.BasedOnStyle);504}505};506507template <>508struct ScalarEnumerationTraits<FormatStyle::ReferenceAlignmentStyle> {509static void enumeration(IO &IO, FormatStyle::ReferenceAlignmentStyle &Value) {510IO.enumCase(Value, "Pointer", FormatStyle::RAS_Pointer);511IO.enumCase(Value, "Middle", FormatStyle::RAS_Middle);512IO.enumCase(Value, "Left", FormatStyle::RAS_Left);513IO.enumCase(Value, "Right", FormatStyle::RAS_Right);514}515};516517template <>518struct ScalarEnumerationTraits<FormatStyle::RemoveParenthesesStyle> {519static void enumeration(IO &IO, FormatStyle::RemoveParenthesesStyle &Value) {520IO.enumCase(Value, "Leave", FormatStyle::RPS_Leave);521IO.enumCase(Value, "MultipleParentheses",522FormatStyle::RPS_MultipleParentheses);523IO.enumCase(Value, "ReturnStatement", FormatStyle::RPS_ReturnStatement);524}525};526527template <>528struct ScalarEnumerationTraits<FormatStyle::RequiresClausePositionStyle> {529static void enumeration(IO &IO,530FormatStyle::RequiresClausePositionStyle &Value) {531IO.enumCase(Value, "OwnLine", FormatStyle::RCPS_OwnLine);532IO.enumCase(Value, "WithPreceding", FormatStyle::RCPS_WithPreceding);533IO.enumCase(Value, "WithFollowing", FormatStyle::RCPS_WithFollowing);534IO.enumCase(Value, "SingleLine", FormatStyle::RCPS_SingleLine);535}536};537538template <>539struct ScalarEnumerationTraits<FormatStyle::RequiresExpressionIndentationKind> {540static void541enumeration(IO &IO, FormatStyle::RequiresExpressionIndentationKind &Value) {542IO.enumCase(Value, "Keyword", FormatStyle::REI_Keyword);543IO.enumCase(Value, "OuterScope", FormatStyle::REI_OuterScope);544}545};546547template <>548struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> {549static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) {550IO.enumCase(Value, "None", FormatStyle::RTBS_None);551IO.enumCase(Value, "Automatic", FormatStyle::RTBS_Automatic);552IO.enumCase(Value, "ExceptShortType", FormatStyle::RTBS_ExceptShortType);553IO.enumCase(Value, "All", FormatStyle::RTBS_All);554IO.enumCase(Value, "TopLevel", FormatStyle::RTBS_TopLevel);555IO.enumCase(Value, "TopLevelDefinitions",556FormatStyle::RTBS_TopLevelDefinitions);557IO.enumCase(Value, "AllDefinitions", FormatStyle::RTBS_AllDefinitions);558}559};560561template <>562struct ScalarEnumerationTraits<FormatStyle::SeparateDefinitionStyle> {563static void enumeration(IO &IO, FormatStyle::SeparateDefinitionStyle &Value) {564IO.enumCase(Value, "Leave", FormatStyle::SDS_Leave);565IO.enumCase(Value, "Always", FormatStyle::SDS_Always);566IO.enumCase(Value, "Never", FormatStyle::SDS_Never);567}568};569570template <> struct ScalarEnumerationTraits<FormatStyle::ShortBlockStyle> {571static void enumeration(IO &IO, FormatStyle::ShortBlockStyle &Value) {572IO.enumCase(Value, "Never", FormatStyle::SBS_Never);573IO.enumCase(Value, "false", FormatStyle::SBS_Never);574IO.enumCase(Value, "Always", FormatStyle::SBS_Always);575IO.enumCase(Value, "true", FormatStyle::SBS_Always);576IO.enumCase(Value, "Empty", FormatStyle::SBS_Empty);577}578};579580template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> {581static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) {582IO.enumCase(Value, "None", FormatStyle::SFS_None);583IO.enumCase(Value, "false", FormatStyle::SFS_None);584IO.enumCase(Value, "All", FormatStyle::SFS_All);585IO.enumCase(Value, "true", FormatStyle::SFS_All);586IO.enumCase(Value, "Inline", FormatStyle::SFS_Inline);587IO.enumCase(Value, "InlineOnly", FormatStyle::SFS_InlineOnly);588IO.enumCase(Value, "Empty", FormatStyle::SFS_Empty);589}590};591592template <> struct ScalarEnumerationTraits<FormatStyle::ShortIfStyle> {593static void enumeration(IO &IO, FormatStyle::ShortIfStyle &Value) {594IO.enumCase(Value, "Never", FormatStyle::SIS_Never);595IO.enumCase(Value, "WithoutElse", FormatStyle::SIS_WithoutElse);596IO.enumCase(Value, "OnlyFirstIf", FormatStyle::SIS_OnlyFirstIf);597IO.enumCase(Value, "AllIfsAndElse", FormatStyle::SIS_AllIfsAndElse);598599// For backward compatibility.600IO.enumCase(Value, "Always", FormatStyle::SIS_OnlyFirstIf);601IO.enumCase(Value, "false", FormatStyle::SIS_Never);602IO.enumCase(Value, "true", FormatStyle::SIS_WithoutElse);603}604};605606template <> struct ScalarEnumerationTraits<FormatStyle::ShortLambdaStyle> {607static void enumeration(IO &IO, FormatStyle::ShortLambdaStyle &Value) {608IO.enumCase(Value, "None", FormatStyle::SLS_None);609IO.enumCase(Value, "false", FormatStyle::SLS_None);610IO.enumCase(Value, "Empty", FormatStyle::SLS_Empty);611IO.enumCase(Value, "Inline", FormatStyle::SLS_Inline);612IO.enumCase(Value, "All", FormatStyle::SLS_All);613IO.enumCase(Value, "true", FormatStyle::SLS_All);614}615};616617template <> struct ScalarEnumerationTraits<FormatStyle::SortIncludesOptions> {618static void enumeration(IO &IO, FormatStyle::SortIncludesOptions &Value) {619IO.enumCase(Value, "Never", FormatStyle::SI_Never);620IO.enumCase(Value, "CaseInsensitive", FormatStyle::SI_CaseInsensitive);621IO.enumCase(Value, "CaseSensitive", FormatStyle::SI_CaseSensitive);622623// For backward compatibility.624IO.enumCase(Value, "false", FormatStyle::SI_Never);625IO.enumCase(Value, "true", FormatStyle::SI_CaseSensitive);626}627};628629template <>630struct ScalarEnumerationTraits<FormatStyle::SortJavaStaticImportOptions> {631static void enumeration(IO &IO,632FormatStyle::SortJavaStaticImportOptions &Value) {633IO.enumCase(Value, "Before", FormatStyle::SJSIO_Before);634IO.enumCase(Value, "After", FormatStyle::SJSIO_After);635}636};637638template <>639struct ScalarEnumerationTraits<FormatStyle::SortUsingDeclarationsOptions> {640static void enumeration(IO &IO,641FormatStyle::SortUsingDeclarationsOptions &Value) {642IO.enumCase(Value, "Never", FormatStyle::SUD_Never);643IO.enumCase(Value, "Lexicographic", FormatStyle::SUD_Lexicographic);644IO.enumCase(Value, "LexicographicNumeric",645FormatStyle::SUD_LexicographicNumeric);646647// For backward compatibility.648IO.enumCase(Value, "false", FormatStyle::SUD_Never);649IO.enumCase(Value, "true", FormatStyle::SUD_LexicographicNumeric);650}651};652653template <>654struct ScalarEnumerationTraits<FormatStyle::SpaceAroundPointerQualifiersStyle> {655static void656enumeration(IO &IO, FormatStyle::SpaceAroundPointerQualifiersStyle &Value) {657IO.enumCase(Value, "Default", FormatStyle::SAPQ_Default);658IO.enumCase(Value, "Before", FormatStyle::SAPQ_Before);659IO.enumCase(Value, "After", FormatStyle::SAPQ_After);660IO.enumCase(Value, "Both", FormatStyle::SAPQ_Both);661}662};663664template <> struct MappingTraits<FormatStyle::SpaceBeforeParensCustom> {665static void mapping(IO &IO, FormatStyle::SpaceBeforeParensCustom &Spacing) {666IO.mapOptional("AfterControlStatements", Spacing.AfterControlStatements);667IO.mapOptional("AfterForeachMacros", Spacing.AfterForeachMacros);668IO.mapOptional("AfterFunctionDefinitionName",669Spacing.AfterFunctionDefinitionName);670IO.mapOptional("AfterFunctionDeclarationName",671Spacing.AfterFunctionDeclarationName);672IO.mapOptional("AfterIfMacros", Spacing.AfterIfMacros);673IO.mapOptional("AfterOverloadedOperator", Spacing.AfterOverloadedOperator);674IO.mapOptional("AfterPlacementOperator", Spacing.AfterPlacementOperator);675IO.mapOptional("AfterRequiresInClause", Spacing.AfterRequiresInClause);676IO.mapOptional("AfterRequiresInExpression",677Spacing.AfterRequiresInExpression);678IO.mapOptional("BeforeNonEmptyParentheses",679Spacing.BeforeNonEmptyParentheses);680}681};682683template <>684struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensStyle> {685static void enumeration(IO &IO, FormatStyle::SpaceBeforeParensStyle &Value) {686IO.enumCase(Value, "Never", FormatStyle::SBPO_Never);687IO.enumCase(Value, "ControlStatements",688FormatStyle::SBPO_ControlStatements);689IO.enumCase(Value, "ControlStatementsExceptControlMacros",690FormatStyle::SBPO_ControlStatementsExceptControlMacros);691IO.enumCase(Value, "NonEmptyParentheses",692FormatStyle::SBPO_NonEmptyParentheses);693IO.enumCase(Value, "Always", FormatStyle::SBPO_Always);694IO.enumCase(Value, "Custom", FormatStyle::SBPO_Custom);695696// For backward compatibility.697IO.enumCase(Value, "false", FormatStyle::SBPO_Never);698IO.enumCase(Value, "true", FormatStyle::SBPO_ControlStatements);699IO.enumCase(Value, "ControlStatementsExceptForEachMacros",700FormatStyle::SBPO_ControlStatementsExceptControlMacros);701}702};703704template <> struct ScalarEnumerationTraits<FormatStyle::SpacesInAnglesStyle> {705static void enumeration(IO &IO, FormatStyle::SpacesInAnglesStyle &Value) {706IO.enumCase(Value, "Never", FormatStyle::SIAS_Never);707IO.enumCase(Value, "Always", FormatStyle::SIAS_Always);708IO.enumCase(Value, "Leave", FormatStyle::SIAS_Leave);709710// For backward compatibility.711IO.enumCase(Value, "false", FormatStyle::SIAS_Never);712IO.enumCase(Value, "true", FormatStyle::SIAS_Always);713}714};715716template <> struct MappingTraits<FormatStyle::SpacesInLineComment> {717static void mapping(IO &IO, FormatStyle::SpacesInLineComment &Space) {718// Transform the maximum to signed, to parse "-1" correctly719int signedMaximum = static_cast<int>(Space.Maximum);720IO.mapOptional("Minimum", Space.Minimum);721IO.mapOptional("Maximum", signedMaximum);722Space.Maximum = static_cast<unsigned>(signedMaximum);723724if (Space.Maximum != -1u)725Space.Minimum = std::min(Space.Minimum, Space.Maximum);726}727};728729template <> struct MappingTraits<FormatStyle::SpacesInParensCustom> {730static void mapping(IO &IO, FormatStyle::SpacesInParensCustom &Spaces) {731IO.mapOptional("ExceptDoubleParentheses", Spaces.ExceptDoubleParentheses);732IO.mapOptional("InCStyleCasts", Spaces.InCStyleCasts);733IO.mapOptional("InConditionalStatements", Spaces.InConditionalStatements);734IO.mapOptional("InEmptyParentheses", Spaces.InEmptyParentheses);735IO.mapOptional("Other", Spaces.Other);736}737};738739template <> struct ScalarEnumerationTraits<FormatStyle::SpacesInParensStyle> {740static void enumeration(IO &IO, FormatStyle::SpacesInParensStyle &Value) {741IO.enumCase(Value, "Never", FormatStyle::SIPO_Never);742IO.enumCase(Value, "Custom", FormatStyle::SIPO_Custom);743}744};745746template <> struct ScalarEnumerationTraits<FormatStyle::TrailingCommaStyle> {747static void enumeration(IO &IO, FormatStyle::TrailingCommaStyle &Value) {748IO.enumCase(Value, "None", FormatStyle::TCS_None);749IO.enumCase(Value, "Wrapped", FormatStyle::TCS_Wrapped);750}751};752753template <>754struct ScalarEnumerationTraits<FormatStyle::TrailingCommentsAlignmentKinds> {755static void enumeration(IO &IO,756FormatStyle::TrailingCommentsAlignmentKinds &Value) {757IO.enumCase(Value, "Leave", FormatStyle::TCAS_Leave);758IO.enumCase(Value, "Always", FormatStyle::TCAS_Always);759IO.enumCase(Value, "Never", FormatStyle::TCAS_Never);760}761};762763template <> struct MappingTraits<FormatStyle::TrailingCommentsAlignmentStyle> {764static void enumInput(IO &IO,765FormatStyle::TrailingCommentsAlignmentStyle &Value) {766IO.enumCase(Value, "Leave",767FormatStyle::TrailingCommentsAlignmentStyle(768{FormatStyle::TCAS_Leave, 0}));769770IO.enumCase(Value, "Always",771FormatStyle::TrailingCommentsAlignmentStyle(772{FormatStyle::TCAS_Always, 0}));773774IO.enumCase(Value, "Never",775FormatStyle::TrailingCommentsAlignmentStyle(776{FormatStyle::TCAS_Never, 0}));777778// For backwards compatibility779IO.enumCase(Value, "true",780FormatStyle::TrailingCommentsAlignmentStyle(781{FormatStyle::TCAS_Always, 0}));782IO.enumCase(Value, "false",783FormatStyle::TrailingCommentsAlignmentStyle(784{FormatStyle::TCAS_Never, 0}));785}786787static void mapping(IO &IO,788FormatStyle::TrailingCommentsAlignmentStyle &Value) {789IO.mapOptional("Kind", Value.Kind);790IO.mapOptional("OverEmptyLines", Value.OverEmptyLines);791}792};793794template <> struct ScalarEnumerationTraits<FormatStyle::UseTabStyle> {795static void enumeration(IO &IO, FormatStyle::UseTabStyle &Value) {796IO.enumCase(Value, "Never", FormatStyle::UT_Never);797IO.enumCase(Value, "false", FormatStyle::UT_Never);798IO.enumCase(Value, "Always", FormatStyle::UT_Always);799IO.enumCase(Value, "true", FormatStyle::UT_Always);800IO.enumCase(Value, "ForIndentation", FormatStyle::UT_ForIndentation);801IO.enumCase(Value, "ForContinuationAndIndentation",802FormatStyle::UT_ForContinuationAndIndentation);803IO.enumCase(Value, "AlignWithSpaces", FormatStyle::UT_AlignWithSpaces);804}805};806807template <> struct MappingTraits<FormatStyle> {808static void mapping(IO &IO, FormatStyle &Style) {809// When reading, read the language first, we need it for getPredefinedStyle.810IO.mapOptional("Language", Style.Language);811812StringRef BasedOnStyle;813if (IO.outputting()) {814StringRef Styles[] = {"LLVM", "Google", "Chromium", "Mozilla",815"WebKit", "GNU", "Microsoft", "clang-format"};816for (StringRef StyleName : Styles) {817FormatStyle PredefinedStyle;818if (getPredefinedStyle(StyleName, Style.Language, &PredefinedStyle) &&819Style == PredefinedStyle) {820BasedOnStyle = StyleName;821break;822}823}824} else {825IO.mapOptional("BasedOnStyle", BasedOnStyle);826if (!BasedOnStyle.empty()) {827FormatStyle::LanguageKind OldLanguage = Style.Language;828FormatStyle::LanguageKind Language =829((FormatStyle *)IO.getContext())->Language;830if (!getPredefinedStyle(BasedOnStyle, Language, &Style)) {831IO.setError(Twine("Unknown value for BasedOnStyle: ", BasedOnStyle));832return;833}834Style.Language = OldLanguage;835}836}837838// Initialize some variables used in the parsing. The using logic is at the839// end.840841// For backward compatibility:842// The default value of ConstructorInitializerAllOnOneLineOrOnePerLine was843// false unless BasedOnStyle was Google or Chromium whereas that of844// AllowAllConstructorInitializersOnNextLine was always true, so the845// equivalent default value of PackConstructorInitializers is PCIS_NextLine846// for Google/Chromium or PCIS_BinPack otherwise. If the deprecated options847// had a non-default value while PackConstructorInitializers has a default848// value, set the latter to an equivalent non-default value if needed.849const bool IsGoogleOrChromium = BasedOnStyle.equals_insensitive("google") ||850BasedOnStyle.equals_insensitive("chromium");851bool OnCurrentLine = IsGoogleOrChromium;852bool OnNextLine = true;853854bool BreakBeforeInheritanceComma = false;855bool BreakConstructorInitializersBeforeComma = false;856857bool DeriveLineEnding = true;858bool UseCRLF = false;859860bool SpaceInEmptyParentheses = false;861bool SpacesInConditionalStatement = false;862bool SpacesInCStyleCastParentheses = false;863bool SpacesInParentheses = false;864865// For backward compatibility.866if (!IO.outputting()) {867IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlines);868IO.mapOptional("AllowAllConstructorInitializersOnNextLine", OnNextLine);869IO.mapOptional("AlwaysBreakAfterReturnType", Style.BreakAfterReturnType);870IO.mapOptional("AlwaysBreakTemplateDeclarations",871Style.BreakTemplateDeclarations);872IO.mapOptional("BreakBeforeInheritanceComma",873BreakBeforeInheritanceComma);874IO.mapOptional("BreakConstructorInitializersBeforeComma",875BreakConstructorInitializersBeforeComma);876IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine",877OnCurrentLine);878IO.mapOptional("DeriveLineEnding", DeriveLineEnding);879IO.mapOptional("DerivePointerBinding", Style.DerivePointerAlignment);880IO.mapOptional("KeepEmptyLinesAtEOF", Style.KeepEmptyLines.AtEndOfFile);881IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks",882Style.KeepEmptyLines.AtStartOfBlock);883IO.mapOptional("IndentFunctionDeclarationAfterType",884Style.IndentWrappedFunctionNames);885IO.mapOptional("IndentRequires", Style.IndentRequiresClause);886IO.mapOptional("PointerBindsToType", Style.PointerAlignment);887IO.mapOptional("SpaceAfterControlStatementKeyword",888Style.SpaceBeforeParens);889IO.mapOptional("SpaceInEmptyParentheses", SpaceInEmptyParentheses);890IO.mapOptional("SpacesInConditionalStatement",891SpacesInConditionalStatement);892IO.mapOptional("SpacesInCStyleCastParentheses",893SpacesInCStyleCastParentheses);894IO.mapOptional("SpacesInParentheses", SpacesInParentheses);895IO.mapOptional("UseCRLF", UseCRLF);896}897898IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset);899IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket);900IO.mapOptional("AlignArrayOfStructures", Style.AlignArrayOfStructures);901IO.mapOptional("AlignConsecutiveAssignments",902Style.AlignConsecutiveAssignments);903IO.mapOptional("AlignConsecutiveBitFields",904Style.AlignConsecutiveBitFields);905IO.mapOptional("AlignConsecutiveDeclarations",906Style.AlignConsecutiveDeclarations);907IO.mapOptional("AlignConsecutiveMacros", Style.AlignConsecutiveMacros);908IO.mapOptional("AlignConsecutiveShortCaseStatements",909Style.AlignConsecutiveShortCaseStatements);910IO.mapOptional("AlignConsecutiveTableGenBreakingDAGArgColons",911Style.AlignConsecutiveTableGenBreakingDAGArgColons);912IO.mapOptional("AlignConsecutiveTableGenCondOperatorColons",913Style.AlignConsecutiveTableGenCondOperatorColons);914IO.mapOptional("AlignConsecutiveTableGenDefinitionColons",915Style.AlignConsecutiveTableGenDefinitionColons);916IO.mapOptional("AlignEscapedNewlines", Style.AlignEscapedNewlines);917IO.mapOptional("AlignOperands", Style.AlignOperands);918IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments);919IO.mapOptional("AllowAllArgumentsOnNextLine",920Style.AllowAllArgumentsOnNextLine);921IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine",922Style.AllowAllParametersOfDeclarationOnNextLine);923IO.mapOptional("AllowBreakBeforeNoexceptSpecifier",924Style.AllowBreakBeforeNoexceptSpecifier);925IO.mapOptional("AllowShortBlocksOnASingleLine",926Style.AllowShortBlocksOnASingleLine);927IO.mapOptional("AllowShortCaseExpressionOnASingleLine",928Style.AllowShortCaseExpressionOnASingleLine);929IO.mapOptional("AllowShortCaseLabelsOnASingleLine",930Style.AllowShortCaseLabelsOnASingleLine);931IO.mapOptional("AllowShortCompoundRequirementOnASingleLine",932Style.AllowShortCompoundRequirementOnASingleLine);933IO.mapOptional("AllowShortEnumsOnASingleLine",934Style.AllowShortEnumsOnASingleLine);935IO.mapOptional("AllowShortFunctionsOnASingleLine",936Style.AllowShortFunctionsOnASingleLine);937IO.mapOptional("AllowShortIfStatementsOnASingleLine",938Style.AllowShortIfStatementsOnASingleLine);939IO.mapOptional("AllowShortLambdasOnASingleLine",940Style.AllowShortLambdasOnASingleLine);941IO.mapOptional("AllowShortLoopsOnASingleLine",942Style.AllowShortLoopsOnASingleLine);943IO.mapOptional("AlwaysBreakAfterDefinitionReturnType",944Style.AlwaysBreakAfterDefinitionReturnType);945IO.mapOptional("AlwaysBreakBeforeMultilineStrings",946Style.AlwaysBreakBeforeMultilineStrings);947IO.mapOptional("AttributeMacros", Style.AttributeMacros);948IO.mapOptional("BinPackArguments", Style.BinPackArguments);949IO.mapOptional("BinPackParameters", Style.BinPackParameters);950IO.mapOptional("BitFieldColonSpacing", Style.BitFieldColonSpacing);951IO.mapOptional("BracedInitializerIndentWidth",952Style.BracedInitializerIndentWidth);953IO.mapOptional("BraceWrapping", Style.BraceWrapping);954IO.mapOptional("BreakAdjacentStringLiterals",955Style.BreakAdjacentStringLiterals);956IO.mapOptional("BreakAfterAttributes", Style.BreakAfterAttributes);957IO.mapOptional("BreakAfterJavaFieldAnnotations",958Style.BreakAfterJavaFieldAnnotations);959IO.mapOptional("BreakAfterReturnType", Style.BreakAfterReturnType);960IO.mapOptional("BreakArrays", Style.BreakArrays);961IO.mapOptional("BreakBeforeBinaryOperators",962Style.BreakBeforeBinaryOperators);963IO.mapOptional("BreakBeforeConceptDeclarations",964Style.BreakBeforeConceptDeclarations);965IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);966IO.mapOptional("BreakBeforeInlineASMColon",967Style.BreakBeforeInlineASMColon);968IO.mapOptional("BreakBeforeTernaryOperators",969Style.BreakBeforeTernaryOperators);970IO.mapOptional("BreakConstructorInitializers",971Style.BreakConstructorInitializers);972IO.mapOptional("BreakFunctionDefinitionParameters",973Style.BreakFunctionDefinitionParameters);974IO.mapOptional("BreakInheritanceList", Style.BreakInheritanceList);975IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals);976IO.mapOptional("BreakTemplateDeclarations",977Style.BreakTemplateDeclarations);978IO.mapOptional("ColumnLimit", Style.ColumnLimit);979IO.mapOptional("CommentPragmas", Style.CommentPragmas);980IO.mapOptional("CompactNamespaces", Style.CompactNamespaces);981IO.mapOptional("ConstructorInitializerIndentWidth",982Style.ConstructorInitializerIndentWidth);983IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth);984IO.mapOptional("Cpp11BracedListStyle", Style.Cpp11BracedListStyle);985IO.mapOptional("DerivePointerAlignment", Style.DerivePointerAlignment);986IO.mapOptional("DisableFormat", Style.DisableFormat);987IO.mapOptional("EmptyLineAfterAccessModifier",988Style.EmptyLineAfterAccessModifier);989IO.mapOptional("EmptyLineBeforeAccessModifier",990Style.EmptyLineBeforeAccessModifier);991IO.mapOptional("ExperimentalAutoDetectBinPacking",992Style.ExperimentalAutoDetectBinPacking);993IO.mapOptional("FixNamespaceComments", Style.FixNamespaceComments);994IO.mapOptional("ForEachMacros", Style.ForEachMacros);995IO.mapOptional("IfMacros", Style.IfMacros);996IO.mapOptional("IncludeBlocks", Style.IncludeStyle.IncludeBlocks);997IO.mapOptional("IncludeCategories", Style.IncludeStyle.IncludeCategories);998IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex);999IO.mapOptional("IncludeIsMainSourceRegex",1000Style.IncludeStyle.IncludeIsMainSourceRegex);1001IO.mapOptional("IndentAccessModifiers", Style.IndentAccessModifiers);1002IO.mapOptional("IndentCaseBlocks", Style.IndentCaseBlocks);1003IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);1004IO.mapOptional("IndentExternBlock", Style.IndentExternBlock);1005IO.mapOptional("IndentGotoLabels", Style.IndentGotoLabels);1006IO.mapOptional("IndentPPDirectives", Style.IndentPPDirectives);1007IO.mapOptional("IndentRequiresClause", Style.IndentRequiresClause);1008IO.mapOptional("IndentWidth", Style.IndentWidth);1009IO.mapOptional("IndentWrappedFunctionNames",1010Style.IndentWrappedFunctionNames);1011IO.mapOptional("InsertBraces", Style.InsertBraces);1012IO.mapOptional("InsertNewlineAtEOF", Style.InsertNewlineAtEOF);1013IO.mapOptional("InsertTrailingCommas", Style.InsertTrailingCommas);1014IO.mapOptional("IntegerLiteralSeparator", Style.IntegerLiteralSeparator);1015IO.mapOptional("JavaImportGroups", Style.JavaImportGroups);1016IO.mapOptional("JavaScriptQuotes", Style.JavaScriptQuotes);1017IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports);1018IO.mapOptional("KeepEmptyLines", Style.KeepEmptyLines);1019IO.mapOptional("LambdaBodyIndentation", Style.LambdaBodyIndentation);1020IO.mapOptional("LineEnding", Style.LineEnding);1021IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin);1022IO.mapOptional("MacroBlockEnd", Style.MacroBlockEnd);1023IO.mapOptional("Macros", Style.Macros);1024IO.mapOptional("MainIncludeChar", Style.IncludeStyle.MainIncludeChar);1025IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep);1026IO.mapOptional("NamespaceIndentation", Style.NamespaceIndentation);1027IO.mapOptional("NamespaceMacros", Style.NamespaceMacros);1028IO.mapOptional("ObjCBinPackProtocolList", Style.ObjCBinPackProtocolList);1029IO.mapOptional("ObjCBlockIndentWidth", Style.ObjCBlockIndentWidth);1030IO.mapOptional("ObjCBreakBeforeNestedBlockParam",1031Style.ObjCBreakBeforeNestedBlockParam);1032IO.mapOptional("ObjCPropertyAttributeOrder",1033Style.ObjCPropertyAttributeOrder);1034IO.mapOptional("ObjCSpaceAfterProperty", Style.ObjCSpaceAfterProperty);1035IO.mapOptional("ObjCSpaceBeforeProtocolList",1036Style.ObjCSpaceBeforeProtocolList);1037IO.mapOptional("PackConstructorInitializers",1038Style.PackConstructorInitializers);1039IO.mapOptional("PenaltyBreakAssignment", Style.PenaltyBreakAssignment);1040IO.mapOptional("PenaltyBreakBeforeFirstCallParameter",1041Style.PenaltyBreakBeforeFirstCallParameter);1042IO.mapOptional("PenaltyBreakComment", Style.PenaltyBreakComment);1043IO.mapOptional("PenaltyBreakFirstLessLess",1044Style.PenaltyBreakFirstLessLess);1045IO.mapOptional("PenaltyBreakOpenParenthesis",1046Style.PenaltyBreakOpenParenthesis);1047IO.mapOptional("PenaltyBreakScopeResolution",1048Style.PenaltyBreakScopeResolution);1049IO.mapOptional("PenaltyBreakString", Style.PenaltyBreakString);1050IO.mapOptional("PenaltyBreakTemplateDeclaration",1051Style.PenaltyBreakTemplateDeclaration);1052IO.mapOptional("PenaltyExcessCharacter", Style.PenaltyExcessCharacter);1053IO.mapOptional("PenaltyIndentedWhitespace",1054Style.PenaltyIndentedWhitespace);1055IO.mapOptional("PenaltyReturnTypeOnItsOwnLine",1056Style.PenaltyReturnTypeOnItsOwnLine);1057IO.mapOptional("PointerAlignment", Style.PointerAlignment);1058IO.mapOptional("PPIndentWidth", Style.PPIndentWidth);1059IO.mapOptional("QualifierAlignment", Style.QualifierAlignment);1060// Default Order for Left/Right based Qualifier alignment.1061if (Style.QualifierAlignment == FormatStyle::QAS_Right)1062Style.QualifierOrder = {"type", "const", "volatile"};1063else if (Style.QualifierAlignment == FormatStyle::QAS_Left)1064Style.QualifierOrder = {"const", "volatile", "type"};1065else if (Style.QualifierAlignment == FormatStyle::QAS_Custom)1066IO.mapOptional("QualifierOrder", Style.QualifierOrder);1067IO.mapOptional("RawStringFormats", Style.RawStringFormats);1068IO.mapOptional("ReferenceAlignment", Style.ReferenceAlignment);1069IO.mapOptional("ReflowComments", Style.ReflowComments);1070IO.mapOptional("RemoveBracesLLVM", Style.RemoveBracesLLVM);1071IO.mapOptional("RemoveParentheses", Style.RemoveParentheses);1072IO.mapOptional("RemoveSemicolon", Style.RemoveSemicolon);1073IO.mapOptional("RequiresClausePosition", Style.RequiresClausePosition);1074IO.mapOptional("RequiresExpressionIndentation",1075Style.RequiresExpressionIndentation);1076IO.mapOptional("SeparateDefinitionBlocks", Style.SeparateDefinitionBlocks);1077IO.mapOptional("ShortNamespaceLines", Style.ShortNamespaceLines);1078IO.mapOptional("SkipMacroDefinitionBody", Style.SkipMacroDefinitionBody);1079IO.mapOptional("SortIncludes", Style.SortIncludes);1080IO.mapOptional("SortJavaStaticImport", Style.SortJavaStaticImport);1081IO.mapOptional("SortUsingDeclarations", Style.SortUsingDeclarations);1082IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast);1083IO.mapOptional("SpaceAfterLogicalNot", Style.SpaceAfterLogicalNot);1084IO.mapOptional("SpaceAfterTemplateKeyword",1085Style.SpaceAfterTemplateKeyword);1086IO.mapOptional("SpaceAroundPointerQualifiers",1087Style.SpaceAroundPointerQualifiers);1088IO.mapOptional("SpaceBeforeAssignmentOperators",1089Style.SpaceBeforeAssignmentOperators);1090IO.mapOptional("SpaceBeforeCaseColon", Style.SpaceBeforeCaseColon);1091IO.mapOptional("SpaceBeforeCpp11BracedList",1092Style.SpaceBeforeCpp11BracedList);1093IO.mapOptional("SpaceBeforeCtorInitializerColon",1094Style.SpaceBeforeCtorInitializerColon);1095IO.mapOptional("SpaceBeforeInheritanceColon",1096Style.SpaceBeforeInheritanceColon);1097IO.mapOptional("SpaceBeforeJsonColon", Style.SpaceBeforeJsonColon);1098IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);1099IO.mapOptional("SpaceBeforeParensOptions", Style.SpaceBeforeParensOptions);1100IO.mapOptional("SpaceBeforeRangeBasedForLoopColon",1101Style.SpaceBeforeRangeBasedForLoopColon);1102IO.mapOptional("SpaceBeforeSquareBrackets",1103Style.SpaceBeforeSquareBrackets);1104IO.mapOptional("SpaceInEmptyBlock", Style.SpaceInEmptyBlock);1105IO.mapOptional("SpacesBeforeTrailingComments",1106Style.SpacesBeforeTrailingComments);1107IO.mapOptional("SpacesInAngles", Style.SpacesInAngles);1108IO.mapOptional("SpacesInContainerLiterals",1109Style.SpacesInContainerLiterals);1110IO.mapOptional("SpacesInLineCommentPrefix",1111Style.SpacesInLineCommentPrefix);1112IO.mapOptional("SpacesInParens", Style.SpacesInParens);1113IO.mapOptional("SpacesInParensOptions", Style.SpacesInParensOptions);1114IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets);1115IO.mapOptional("Standard", Style.Standard);1116IO.mapOptional("StatementAttributeLikeMacros",1117Style.StatementAttributeLikeMacros);1118IO.mapOptional("StatementMacros", Style.StatementMacros);1119IO.mapOptional("TableGenBreakingDAGArgOperators",1120Style.TableGenBreakingDAGArgOperators);1121IO.mapOptional("TableGenBreakInsideDAGArg",1122Style.TableGenBreakInsideDAGArg);1123IO.mapOptional("TabWidth", Style.TabWidth);1124IO.mapOptional("TypeNames", Style.TypeNames);1125IO.mapOptional("TypenameMacros", Style.TypenameMacros);1126IO.mapOptional("UseTab", Style.UseTab);1127IO.mapOptional("VerilogBreakBetweenInstancePorts",1128Style.VerilogBreakBetweenInstancePorts);1129IO.mapOptional("WhitespaceSensitiveMacros",1130Style.WhitespaceSensitiveMacros);11311132// If AlwaysBreakAfterDefinitionReturnType was specified but1133// BreakAfterReturnType was not, initialize the latter from the former for1134// backwards compatibility.1135if (Style.AlwaysBreakAfterDefinitionReturnType != FormatStyle::DRTBS_None &&1136Style.BreakAfterReturnType == FormatStyle::RTBS_None) {1137if (Style.AlwaysBreakAfterDefinitionReturnType ==1138FormatStyle::DRTBS_All) {1139Style.BreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;1140} else if (Style.AlwaysBreakAfterDefinitionReturnType ==1141FormatStyle::DRTBS_TopLevel) {1142Style.BreakAfterReturnType = FormatStyle::RTBS_TopLevelDefinitions;1143}1144}11451146// If BreakBeforeInheritanceComma was specified but BreakInheritance was1147// not, initialize the latter from the former for backwards compatibility.1148if (BreakBeforeInheritanceComma &&1149Style.BreakInheritanceList == FormatStyle::BILS_BeforeColon) {1150Style.BreakInheritanceList = FormatStyle::BILS_BeforeComma;1151}11521153// If BreakConstructorInitializersBeforeComma was specified but1154// BreakConstructorInitializers was not, initialize the latter from the1155// former for backwards compatibility.1156if (BreakConstructorInitializersBeforeComma &&1157Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon) {1158Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;1159}11601161if (!IsGoogleOrChromium) {1162if (Style.PackConstructorInitializers == FormatStyle::PCIS_BinPack &&1163OnCurrentLine) {1164Style.PackConstructorInitializers = OnNextLine1165? FormatStyle::PCIS_NextLine1166: FormatStyle::PCIS_CurrentLine;1167}1168} else if (Style.PackConstructorInitializers ==1169FormatStyle::PCIS_NextLine) {1170if (!OnCurrentLine)1171Style.PackConstructorInitializers = FormatStyle::PCIS_BinPack;1172else if (!OnNextLine)1173Style.PackConstructorInitializers = FormatStyle::PCIS_CurrentLine;1174}11751176if (Style.LineEnding == FormatStyle::LE_DeriveLF) {1177if (!DeriveLineEnding)1178Style.LineEnding = UseCRLF ? FormatStyle::LE_CRLF : FormatStyle::LE_LF;1179else if (UseCRLF)1180Style.LineEnding = FormatStyle::LE_DeriveCRLF;1181}11821183if (Style.SpacesInParens != FormatStyle::SIPO_Custom &&1184(SpacesInParentheses || SpaceInEmptyParentheses ||1185SpacesInConditionalStatement || SpacesInCStyleCastParentheses)) {1186if (SpacesInParentheses) {1187// For backward compatibility.1188Style.SpacesInParensOptions.ExceptDoubleParentheses = false;1189Style.SpacesInParensOptions.InConditionalStatements = true;1190Style.SpacesInParensOptions.InCStyleCasts =1191SpacesInCStyleCastParentheses;1192Style.SpacesInParensOptions.InEmptyParentheses =1193SpaceInEmptyParentheses;1194Style.SpacesInParensOptions.Other = true;1195} else {1196Style.SpacesInParensOptions = {};1197Style.SpacesInParensOptions.InConditionalStatements =1198SpacesInConditionalStatement;1199Style.SpacesInParensOptions.InCStyleCasts =1200SpacesInCStyleCastParentheses;1201Style.SpacesInParensOptions.InEmptyParentheses =1202SpaceInEmptyParentheses;1203}1204Style.SpacesInParens = FormatStyle::SIPO_Custom;1205}1206}1207};12081209// Allows to read vector<FormatStyle> while keeping default values.1210// IO.getContext() should contain a pointer to the FormatStyle structure, that1211// will be used to get default values for missing keys.1212// If the first element has no Language specified, it will be treated as the1213// default one for the following elements.1214template <> struct DocumentListTraits<std::vector<FormatStyle>> {1215static size_t size(IO &IO, std::vector<FormatStyle> &Seq) {1216return Seq.size();1217}1218static FormatStyle &element(IO &IO, std::vector<FormatStyle> &Seq,1219size_t Index) {1220if (Index >= Seq.size()) {1221assert(Index == Seq.size());1222FormatStyle Template;1223if (!Seq.empty() && Seq[0].Language == FormatStyle::LK_None) {1224Template = Seq[0];1225} else {1226Template = *((const FormatStyle *)IO.getContext());1227Template.Language = FormatStyle::LK_None;1228}1229Seq.resize(Index + 1, Template);1230}1231return Seq[Index];1232}1233};1234} // namespace yaml1235} // namespace llvm12361237namespace clang {1238namespace format {12391240const std::error_category &getParseCategory() {1241static const ParseErrorCategory C{};1242return C;1243}1244std::error_code make_error_code(ParseError e) {1245return std::error_code(static_cast<int>(e), getParseCategory());1246}12471248inline llvm::Error make_string_error(const Twine &Message) {1249return llvm::make_error<llvm::StringError>(Message,1250llvm::inconvertibleErrorCode());1251}12521253const char *ParseErrorCategory::name() const noexcept {1254return "clang-format.parse_error";1255}12561257std::string ParseErrorCategory::message(int EV) const {1258switch (static_cast<ParseError>(EV)) {1259case ParseError::Success:1260return "Success";1261case ParseError::Error:1262return "Invalid argument";1263case ParseError::Unsuitable:1264return "Unsuitable";1265case ParseError::BinPackTrailingCommaConflict:1266return "trailing comma insertion cannot be used with bin packing";1267case ParseError::InvalidQualifierSpecified:1268return "Invalid qualifier specified in QualifierOrder";1269case ParseError::DuplicateQualifierSpecified:1270return "Duplicate qualifier specified in QualifierOrder";1271case ParseError::MissingQualifierType:1272return "Missing type in QualifierOrder";1273case ParseError::MissingQualifierOrder:1274return "Missing QualifierOrder";1275}1276llvm_unreachable("unexpected parse error");1277}12781279static void expandPresetsBraceWrapping(FormatStyle &Expanded) {1280if (Expanded.BreakBeforeBraces == FormatStyle::BS_Custom)1281return;1282Expanded.BraceWrapping = {/*AfterCaseLabel=*/false,1283/*AfterClass=*/false,1284/*AfterControlStatement=*/FormatStyle::BWACS_Never,1285/*AfterEnum=*/false,1286/*AfterFunction=*/false,1287/*AfterNamespace=*/false,1288/*AfterObjCDeclaration=*/false,1289/*AfterStruct=*/false,1290/*AfterUnion=*/false,1291/*AfterExternBlock=*/false,1292/*BeforeCatch=*/false,1293/*BeforeElse=*/false,1294/*BeforeLambdaBody=*/false,1295/*BeforeWhile=*/false,1296/*IndentBraces=*/false,1297/*SplitEmptyFunction=*/true,1298/*SplitEmptyRecord=*/true,1299/*SplitEmptyNamespace=*/true};1300switch (Expanded.BreakBeforeBraces) {1301case FormatStyle::BS_Linux:1302Expanded.BraceWrapping.AfterClass = true;1303Expanded.BraceWrapping.AfterFunction = true;1304Expanded.BraceWrapping.AfterNamespace = true;1305break;1306case FormatStyle::BS_Mozilla:1307Expanded.BraceWrapping.AfterClass = true;1308Expanded.BraceWrapping.AfterEnum = true;1309Expanded.BraceWrapping.AfterFunction = true;1310Expanded.BraceWrapping.AfterStruct = true;1311Expanded.BraceWrapping.AfterUnion = true;1312Expanded.BraceWrapping.AfterExternBlock = true;1313Expanded.BraceWrapping.SplitEmptyFunction = true;1314Expanded.BraceWrapping.SplitEmptyRecord = false;1315break;1316case FormatStyle::BS_Stroustrup:1317Expanded.BraceWrapping.AfterFunction = true;1318Expanded.BraceWrapping.BeforeCatch = true;1319Expanded.BraceWrapping.BeforeElse = true;1320break;1321case FormatStyle::BS_Allman:1322Expanded.BraceWrapping.AfterCaseLabel = true;1323Expanded.BraceWrapping.AfterClass = true;1324Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;1325Expanded.BraceWrapping.AfterEnum = true;1326Expanded.BraceWrapping.AfterFunction = true;1327Expanded.BraceWrapping.AfterNamespace = true;1328Expanded.BraceWrapping.AfterObjCDeclaration = true;1329Expanded.BraceWrapping.AfterStruct = true;1330Expanded.BraceWrapping.AfterUnion = true;1331Expanded.BraceWrapping.AfterExternBlock = true;1332Expanded.BraceWrapping.BeforeCatch = true;1333Expanded.BraceWrapping.BeforeElse = true;1334Expanded.BraceWrapping.BeforeLambdaBody = true;1335break;1336case FormatStyle::BS_Whitesmiths:1337Expanded.BraceWrapping.AfterCaseLabel = true;1338Expanded.BraceWrapping.AfterClass = true;1339Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;1340Expanded.BraceWrapping.AfterEnum = true;1341Expanded.BraceWrapping.AfterFunction = true;1342Expanded.BraceWrapping.AfterNamespace = true;1343Expanded.BraceWrapping.AfterObjCDeclaration = true;1344Expanded.BraceWrapping.AfterStruct = true;1345Expanded.BraceWrapping.AfterExternBlock = true;1346Expanded.BraceWrapping.BeforeCatch = true;1347Expanded.BraceWrapping.BeforeElse = true;1348Expanded.BraceWrapping.BeforeLambdaBody = true;1349break;1350case FormatStyle::BS_GNU:1351Expanded.BraceWrapping = {1352/*AfterCaseLabel=*/true,1353/*AfterClass=*/true,1354/*AfterControlStatement=*/FormatStyle::BWACS_Always,1355/*AfterEnum=*/true,1356/*AfterFunction=*/true,1357/*AfterNamespace=*/true,1358/*AfterObjCDeclaration=*/true,1359/*AfterStruct=*/true,1360/*AfterUnion=*/true,1361/*AfterExternBlock=*/true,1362/*BeforeCatch=*/true,1363/*BeforeElse=*/true,1364/*BeforeLambdaBody=*/false,1365/*BeforeWhile=*/true,1366/*IndentBraces=*/true,1367/*SplitEmptyFunction=*/true,1368/*SplitEmptyRecord=*/true,1369/*SplitEmptyNamespace=*/true};1370break;1371case FormatStyle::BS_WebKit:1372Expanded.BraceWrapping.AfterFunction = true;1373break;1374default:1375break;1376}1377}13781379static void expandPresetsSpaceBeforeParens(FormatStyle &Expanded) {1380if (Expanded.SpaceBeforeParens == FormatStyle::SBPO_Custom)1381return;1382// Reset all flags1383Expanded.SpaceBeforeParensOptions = {};1384Expanded.SpaceBeforeParensOptions.AfterPlacementOperator = true;13851386switch (Expanded.SpaceBeforeParens) {1387case FormatStyle::SBPO_ControlStatements:1388Expanded.SpaceBeforeParensOptions.AfterControlStatements = true;1389Expanded.SpaceBeforeParensOptions.AfterForeachMacros = true;1390Expanded.SpaceBeforeParensOptions.AfterIfMacros = true;1391break;1392case FormatStyle::SBPO_ControlStatementsExceptControlMacros:1393Expanded.SpaceBeforeParensOptions.AfterControlStatements = true;1394break;1395case FormatStyle::SBPO_NonEmptyParentheses:1396Expanded.SpaceBeforeParensOptions.BeforeNonEmptyParentheses = true;1397break;1398default:1399break;1400}1401}14021403static void expandPresetsSpacesInParens(FormatStyle &Expanded) {1404if (Expanded.SpacesInParens == FormatStyle::SIPO_Custom)1405return;1406assert(Expanded.SpacesInParens == FormatStyle::SIPO_Never);1407// Reset all flags1408Expanded.SpacesInParensOptions = {};1409}14101411FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {1412FormatStyle LLVMStyle;1413LLVMStyle.AccessModifierOffset = -2;1414LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align;1415LLVMStyle.AlignArrayOfStructures = FormatStyle::AIAS_None;1416LLVMStyle.AlignConsecutiveAssignments = {};1417LLVMStyle.AlignConsecutiveAssignments.AcrossComments = false;1418LLVMStyle.AlignConsecutiveAssignments.AcrossEmptyLines = false;1419LLVMStyle.AlignConsecutiveAssignments.AlignCompound = false;1420LLVMStyle.AlignConsecutiveAssignments.AlignFunctionPointers = false;1421LLVMStyle.AlignConsecutiveAssignments.Enabled = false;1422LLVMStyle.AlignConsecutiveAssignments.PadOperators = true;1423LLVMStyle.AlignConsecutiveBitFields = {};1424LLVMStyle.AlignConsecutiveDeclarations = {};1425LLVMStyle.AlignConsecutiveMacros = {};1426LLVMStyle.AlignConsecutiveShortCaseStatements = {};1427LLVMStyle.AlignConsecutiveTableGenBreakingDAGArgColons = {};1428LLVMStyle.AlignConsecutiveTableGenCondOperatorColons = {};1429LLVMStyle.AlignConsecutiveTableGenDefinitionColons = {};1430LLVMStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right;1431LLVMStyle.AlignOperands = FormatStyle::OAS_Align;1432LLVMStyle.AlignTrailingComments = {};1433LLVMStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Always;1434LLVMStyle.AlignTrailingComments.OverEmptyLines = 0;1435LLVMStyle.AllowAllArgumentsOnNextLine = true;1436LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;1437LLVMStyle.AllowBreakBeforeNoexceptSpecifier = FormatStyle::BBNSS_Never;1438LLVMStyle.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never;1439LLVMStyle.AllowShortCaseExpressionOnASingleLine = true;1440LLVMStyle.AllowShortCaseLabelsOnASingleLine = false;1441LLVMStyle.AllowShortCompoundRequirementOnASingleLine = true;1442LLVMStyle.AllowShortEnumsOnASingleLine = true;1443LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;1444LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;1445LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All;1446LLVMStyle.AllowShortLoopsOnASingleLine = false;1447LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;1448LLVMStyle.AlwaysBreakBeforeMultilineStrings = false;1449LLVMStyle.AttributeMacros.push_back("__capability");1450LLVMStyle.BinPackArguments = true;1451LLVMStyle.BinPackParameters = true;1452LLVMStyle.BitFieldColonSpacing = FormatStyle::BFCS_Both;1453LLVMStyle.BracedInitializerIndentWidth = std::nullopt;1454LLVMStyle.BraceWrapping = {/*AfterCaseLabel=*/false,1455/*AfterClass=*/false,1456/*AfterControlStatement=*/FormatStyle::BWACS_Never,1457/*AfterEnum=*/false,1458/*AfterFunction=*/false,1459/*AfterNamespace=*/false,1460/*AfterObjCDeclaration=*/false,1461/*AfterStruct=*/false,1462/*AfterUnion=*/false,1463/*AfterExternBlock=*/false,1464/*BeforeCatch=*/false,1465/*BeforeElse=*/false,1466/*BeforeLambdaBody=*/false,1467/*BeforeWhile=*/false,1468/*IndentBraces=*/false,1469/*SplitEmptyFunction=*/true,1470/*SplitEmptyRecord=*/true,1471/*SplitEmptyNamespace=*/true};1472LLVMStyle.BreakAdjacentStringLiterals = true;1473LLVMStyle.BreakAfterAttributes = FormatStyle::ABS_Leave;1474LLVMStyle.BreakAfterJavaFieldAnnotations = false;1475LLVMStyle.BreakAfterReturnType = FormatStyle::RTBS_None;1476LLVMStyle.BreakArrays = true;1477LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None;1478LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;1479LLVMStyle.BreakBeforeConceptDeclarations = FormatStyle::BBCDS_Always;1480LLVMStyle.BreakBeforeInlineASMColon = FormatStyle::BBIAS_OnlyMultiline;1481LLVMStyle.BreakBeforeTernaryOperators = true;1482LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;1483LLVMStyle.BreakFunctionDefinitionParameters = false;1484LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;1485LLVMStyle.BreakStringLiterals = true;1486LLVMStyle.BreakTemplateDeclarations = FormatStyle::BTDS_MultiLine;1487LLVMStyle.ColumnLimit = 80;1488LLVMStyle.CommentPragmas = "^ IWYU pragma:";1489LLVMStyle.CompactNamespaces = false;1490LLVMStyle.ConstructorInitializerIndentWidth = 4;1491LLVMStyle.ContinuationIndentWidth = 4;1492LLVMStyle.Cpp11BracedListStyle = true;1493LLVMStyle.DerivePointerAlignment = false;1494LLVMStyle.DisableFormat = false;1495LLVMStyle.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Never;1496LLVMStyle.EmptyLineBeforeAccessModifier = FormatStyle::ELBAMS_LogicalBlock;1497LLVMStyle.ExperimentalAutoDetectBinPacking = false;1498LLVMStyle.FixNamespaceComments = true;1499LLVMStyle.ForEachMacros.push_back("foreach");1500LLVMStyle.ForEachMacros.push_back("Q_FOREACH");1501LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH");1502LLVMStyle.IfMacros.push_back("KJ_IF_MAYBE");1503LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve;1504LLVMStyle.IncludeStyle.IncludeCategories = {1505{"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0, false},1506{"^(<|\"(gtest|gmock|isl|json)/)", 3, 0, false},1507{".*", 1, 0, false}};1508LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$";1509LLVMStyle.IncludeStyle.MainIncludeChar = tooling::IncludeStyle::MICD_Quote;1510LLVMStyle.IndentAccessModifiers = false;1511LLVMStyle.IndentCaseBlocks = false;1512LLVMStyle.IndentCaseLabels = false;1513LLVMStyle.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;1514LLVMStyle.IndentGotoLabels = true;1515LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None;1516LLVMStyle.IndentRequiresClause = true;1517LLVMStyle.IndentWidth = 2;1518LLVMStyle.IndentWrappedFunctionNames = false;1519LLVMStyle.InheritsParentConfig = false;1520LLVMStyle.InsertBraces = false;1521LLVMStyle.InsertNewlineAtEOF = false;1522LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None;1523LLVMStyle.IntegerLiteralSeparator = {1524/*Binary=*/0, /*BinaryMinDigits=*/0,1525/*Decimal=*/0, /*DecimalMinDigits=*/0,1526/*Hex=*/0, /*HexMinDigits=*/0};1527LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;1528LLVMStyle.JavaScriptWrapImports = true;1529LLVMStyle.KeepEmptyLines = {1530/*AtEndOfFile=*/false,1531/*AtStartOfBlock=*/true,1532/*AtStartOfFile=*/true,1533};1534LLVMStyle.LambdaBodyIndentation = FormatStyle::LBI_Signature;1535LLVMStyle.Language = Language;1536LLVMStyle.LineEnding = FormatStyle::LE_DeriveLF;1537LLVMStyle.MaxEmptyLinesToKeep = 1;1538LLVMStyle.NamespaceIndentation = FormatStyle::NI_None;1539LLVMStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Auto;1540LLVMStyle.ObjCBlockIndentWidth = 2;1541LLVMStyle.ObjCBreakBeforeNestedBlockParam = true;1542LLVMStyle.ObjCSpaceAfterProperty = false;1543LLVMStyle.ObjCSpaceBeforeProtocolList = true;1544LLVMStyle.PackConstructorInitializers = FormatStyle::PCIS_BinPack;1545LLVMStyle.PointerAlignment = FormatStyle::PAS_Right;1546LLVMStyle.PPIndentWidth = -1;1547LLVMStyle.QualifierAlignment = FormatStyle::QAS_Leave;1548LLVMStyle.ReferenceAlignment = FormatStyle::RAS_Pointer;1549LLVMStyle.ReflowComments = true;1550LLVMStyle.RemoveBracesLLVM = false;1551LLVMStyle.RemoveParentheses = FormatStyle::RPS_Leave;1552LLVMStyle.RemoveSemicolon = false;1553LLVMStyle.RequiresClausePosition = FormatStyle::RCPS_OwnLine;1554LLVMStyle.RequiresExpressionIndentation = FormatStyle::REI_OuterScope;1555LLVMStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Leave;1556LLVMStyle.ShortNamespaceLines = 1;1557LLVMStyle.SkipMacroDefinitionBody = false;1558LLVMStyle.SortIncludes = FormatStyle::SI_CaseSensitive;1559LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before;1560LLVMStyle.SortUsingDeclarations = FormatStyle::SUD_LexicographicNumeric;1561LLVMStyle.SpaceAfterCStyleCast = false;1562LLVMStyle.SpaceAfterLogicalNot = false;1563LLVMStyle.SpaceAfterTemplateKeyword = true;1564LLVMStyle.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Default;1565LLVMStyle.SpaceBeforeAssignmentOperators = true;1566LLVMStyle.SpaceBeforeCaseColon = false;1567LLVMStyle.SpaceBeforeCpp11BracedList = false;1568LLVMStyle.SpaceBeforeCtorInitializerColon = true;1569LLVMStyle.SpaceBeforeInheritanceColon = true;1570LLVMStyle.SpaceBeforeJsonColon = false;1571LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;1572LLVMStyle.SpaceBeforeParensOptions = {};1573LLVMStyle.SpaceBeforeParensOptions.AfterControlStatements = true;1574LLVMStyle.SpaceBeforeParensOptions.AfterForeachMacros = true;1575LLVMStyle.SpaceBeforeParensOptions.AfterIfMacros = true;1576LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true;1577LLVMStyle.SpaceBeforeSquareBrackets = false;1578LLVMStyle.SpaceInEmptyBlock = false;1579LLVMStyle.SpacesBeforeTrailingComments = 1;1580LLVMStyle.SpacesInAngles = FormatStyle::SIAS_Never;1581LLVMStyle.SpacesInContainerLiterals = true;1582LLVMStyle.SpacesInLineCommentPrefix = {/*Minimum=*/1, /*Maximum=*/-1u};1583LLVMStyle.SpacesInParens = FormatStyle::SIPO_Never;1584LLVMStyle.SpacesInSquareBrackets = false;1585LLVMStyle.Standard = FormatStyle::LS_Latest;1586LLVMStyle.StatementAttributeLikeMacros.push_back("Q_EMIT");1587LLVMStyle.StatementMacros.push_back("Q_UNUSED");1588LLVMStyle.StatementMacros.push_back("QT_REQUIRE_VERSION");1589LLVMStyle.TableGenBreakingDAGArgOperators = {};1590LLVMStyle.TableGenBreakInsideDAGArg = FormatStyle::DAS_DontBreak;1591LLVMStyle.TabWidth = 8;1592LLVMStyle.UseTab = FormatStyle::UT_Never;1593LLVMStyle.VerilogBreakBetweenInstancePorts = true;1594LLVMStyle.WhitespaceSensitiveMacros.push_back("BOOST_PP_STRINGIZE");1595LLVMStyle.WhitespaceSensitiveMacros.push_back("CF_SWIFT_NAME");1596LLVMStyle.WhitespaceSensitiveMacros.push_back("NS_SWIFT_NAME");1597LLVMStyle.WhitespaceSensitiveMacros.push_back("PP_STRINGIZE");1598LLVMStyle.WhitespaceSensitiveMacros.push_back("STRINGIZE");15991600LLVMStyle.PenaltyBreakAssignment = prec::Assignment;1601LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19;1602LLVMStyle.PenaltyBreakComment = 300;1603LLVMStyle.PenaltyBreakFirstLessLess = 120;1604LLVMStyle.PenaltyBreakOpenParenthesis = 0;1605LLVMStyle.PenaltyBreakScopeResolution = 500;1606LLVMStyle.PenaltyBreakString = 1000;1607LLVMStyle.PenaltyBreakTemplateDeclaration = prec::Relational;1608LLVMStyle.PenaltyExcessCharacter = 1'000'000;1609LLVMStyle.PenaltyIndentedWhitespace = 0;1610LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60;16111612// Defaults that differ when not C++.1613switch (Language) {1614case FormatStyle::LK_TableGen:1615LLVMStyle.SpacesInContainerLiterals = false;1616break;1617case FormatStyle::LK_Json:1618LLVMStyle.ColumnLimit = 0;1619break;1620case FormatStyle::LK_Verilog:1621LLVMStyle.IndentCaseLabels = true;1622LLVMStyle.SpacesInContainerLiterals = false;1623break;1624default:1625break;1626}16271628return LLVMStyle;1629}16301631FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {1632if (Language == FormatStyle::LK_TextProto) {1633FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_Proto);1634GoogleStyle.Language = FormatStyle::LK_TextProto;16351636return GoogleStyle;1637}16381639FormatStyle GoogleStyle = getLLVMStyle(Language);16401641GoogleStyle.AccessModifierOffset = -1;1642GoogleStyle.AlignEscapedNewlines = FormatStyle::ENAS_Left;1643GoogleStyle.AllowShortIfStatementsOnASingleLine =1644FormatStyle::SIS_WithoutElse;1645GoogleStyle.AllowShortLoopsOnASingleLine = true;1646GoogleStyle.AlwaysBreakBeforeMultilineStrings = true;1647GoogleStyle.BreakTemplateDeclarations = FormatStyle::BTDS_Yes;1648GoogleStyle.DerivePointerAlignment = true;1649GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;1650GoogleStyle.IncludeStyle.IncludeCategories = {{"^<ext/.*\\.h>", 2, 0, false},1651{"^<.*\\.h>", 1, 0, false},1652{"^<.*", 2, 0, false},1653{".*", 3, 0, false}};1654GoogleStyle.IncludeStyle.IncludeIsMainRegex = "([-_](test|unittest))?$";1655GoogleStyle.IndentCaseLabels = true;1656GoogleStyle.KeepEmptyLines.AtStartOfBlock = false;1657GoogleStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Never;1658GoogleStyle.ObjCSpaceAfterProperty = false;1659GoogleStyle.ObjCSpaceBeforeProtocolList = true;1660GoogleStyle.PackConstructorInitializers = FormatStyle::PCIS_NextLine;1661GoogleStyle.PointerAlignment = FormatStyle::PAS_Left;1662GoogleStyle.RawStringFormats = {1663{1664FormatStyle::LK_Cpp,1665/*Delimiters=*/1666{1667"cc",1668"CC",1669"cpp",1670"Cpp",1671"CPP",1672"c++",1673"C++",1674},1675/*EnclosingFunctionNames=*/1676{},1677/*CanonicalDelimiter=*/"",1678/*BasedOnStyle=*/"google",1679},1680{1681FormatStyle::LK_TextProto,1682/*Delimiters=*/1683{1684"pb",1685"PB",1686"proto",1687"PROTO",1688},1689/*EnclosingFunctionNames=*/1690{1691"EqualsProto",1692"EquivToProto",1693"PARSE_PARTIAL_TEXT_PROTO",1694"PARSE_TEST_PROTO",1695"PARSE_TEXT_PROTO",1696"ParseTextOrDie",1697"ParseTextProtoOrDie",1698"ParseTestProto",1699"ParsePartialTestProto",1700},1701/*CanonicalDelimiter=*/"pb",1702/*BasedOnStyle=*/"google",1703},1704};17051706GoogleStyle.SpacesBeforeTrailingComments = 2;1707GoogleStyle.Standard = FormatStyle::LS_Auto;17081709GoogleStyle.PenaltyBreakBeforeFirstCallParameter = 1;1710GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200;17111712if (Language == FormatStyle::LK_Java) {1713GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;1714GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;1715GoogleStyle.AlignTrailingComments = {};1716GoogleStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Never;1717GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;1718GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;1719GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;1720GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment;1721GoogleStyle.ColumnLimit = 100;1722GoogleStyle.SpaceAfterCStyleCast = true;1723GoogleStyle.SpacesBeforeTrailingComments = 1;1724} else if (Language == FormatStyle::LK_JavaScript) {1725GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;1726GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;1727GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;1728// TODO: still under discussion whether to switch to SLS_All.1729GoogleStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty;1730GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;1731GoogleStyle.BreakBeforeTernaryOperators = false;1732// taze:, triple slash directives (`/// <...`), tslint:, and @see, which is1733// commonly followed by overlong URLs.1734GoogleStyle.CommentPragmas = "(taze:|^/[ \t]*<|tslint:|@see)";1735// TODO: enable once decided, in particular re disabling bin packing.1736// https://google.github.io/styleguide/jsguide.html#features-arrays-trailing-comma1737// GoogleStyle.InsertTrailingCommas = FormatStyle::TCS_Wrapped;1738GoogleStyle.JavaScriptQuotes = FormatStyle::JSQS_Single;1739GoogleStyle.JavaScriptWrapImports = false;1740GoogleStyle.MaxEmptyLinesToKeep = 3;1741GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;1742GoogleStyle.SpacesInContainerLiterals = false;1743} else if (Language == FormatStyle::LK_Proto) {1744GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;1745GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;1746// This affects protocol buffer options specifications and text protos.1747// Text protos are currently mostly formatted inside C++ raw string literals1748// and often the current breaking behavior of string literals is not1749// beneficial there. Investigate turning this on once proper string reflow1750// has been implemented.1751GoogleStyle.BreakStringLiterals = false;1752GoogleStyle.Cpp11BracedListStyle = false;1753GoogleStyle.SpacesInContainerLiterals = false;1754} else if (Language == FormatStyle::LK_ObjC) {1755GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;1756GoogleStyle.ColumnLimit = 100;1757// "Regroup" doesn't work well for ObjC yet (main header heuristic,1758// relationship between ObjC standard library headers and other heades,1759// #imports, etc.)1760GoogleStyle.IncludeStyle.IncludeBlocks =1761tooling::IncludeStyle::IBS_Preserve;1762} else if (Language == FormatStyle::LK_CSharp) {1763GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;1764GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;1765GoogleStyle.BreakStringLiterals = false;1766GoogleStyle.ColumnLimit = 100;1767GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;1768}17691770return GoogleStyle;1771}17721773FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) {1774FormatStyle ChromiumStyle = getGoogleStyle(Language);17751776// Disable include reordering across blocks in Chromium code.1777// - clang-format tries to detect that foo.h is the "main" header for1778// foo.cc and foo_unittest.cc via IncludeIsMainRegex. However, Chromium1779// uses many other suffices (_win.cc, _mac.mm, _posix.cc, _browsertest.cc,1780// _private.cc, _impl.cc etc) in different permutations1781// (_win_browsertest.cc) so disable this until IncludeIsMainRegex has a1782// better default for Chromium code.1783// - The default for .cc and .mm files is different (r357695) for Google style1784// for the same reason. The plan is to unify this again once the main1785// header detection works for Google's ObjC code, but this hasn't happened1786// yet. Since Chromium has some ObjC code, switching Chromium is blocked1787// on that.1788// - Finally, "If include reordering is harmful, put things in different1789// blocks to prevent it" has been a recommendation for a long time that1790// people are used to. We'll need a dev education push to change this to1791// "If include reordering is harmful, put things in a different block and1792// _prepend that with a comment_ to prevent it" before changing behavior.1793ChromiumStyle.IncludeStyle.IncludeBlocks =1794tooling::IncludeStyle::IBS_Preserve;17951796if (Language == FormatStyle::LK_Java) {1797ChromiumStyle.AllowShortIfStatementsOnASingleLine =1798FormatStyle::SIS_WithoutElse;1799ChromiumStyle.BreakAfterJavaFieldAnnotations = true;1800ChromiumStyle.ContinuationIndentWidth = 8;1801ChromiumStyle.IndentWidth = 4;1802// See styleguide for import groups:1803// https://chromium.googlesource.com/chromium/src/+/refs/heads/main/styleguide/java/java.md#Import-Order1804ChromiumStyle.JavaImportGroups = {1805"android",1806"androidx",1807"com",1808"dalvik",1809"junit",1810"org",1811"com.google.android.apps.chrome",1812"org.chromium",1813"java",1814"javax",1815};1816ChromiumStyle.SortIncludes = FormatStyle::SI_CaseSensitive;1817} else if (Language == FormatStyle::LK_JavaScript) {1818ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;1819ChromiumStyle.AllowShortLoopsOnASingleLine = false;1820} else {1821ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false;1822ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;1823ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;1824ChromiumStyle.AllowShortLoopsOnASingleLine = false;1825ChromiumStyle.BinPackParameters = false;1826ChromiumStyle.DerivePointerAlignment = false;1827if (Language == FormatStyle::LK_ObjC)1828ChromiumStyle.ColumnLimit = 80;1829}1830return ChromiumStyle;1831}18321833FormatStyle getMozillaStyle() {1834FormatStyle MozillaStyle = getLLVMStyle();1835MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false;1836MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;1837MozillaStyle.AlwaysBreakAfterDefinitionReturnType =1838FormatStyle::DRTBS_TopLevel;1839MozillaStyle.BinPackArguments = false;1840MozillaStyle.BinPackParameters = false;1841MozillaStyle.BreakAfterReturnType = FormatStyle::RTBS_TopLevel;1842MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla;1843MozillaStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;1844MozillaStyle.BreakInheritanceList = FormatStyle::BILS_BeforeComma;1845MozillaStyle.BreakTemplateDeclarations = FormatStyle::BTDS_Yes;1846MozillaStyle.ConstructorInitializerIndentWidth = 2;1847MozillaStyle.ContinuationIndentWidth = 2;1848MozillaStyle.Cpp11BracedListStyle = false;1849MozillaStyle.FixNamespaceComments = false;1850MozillaStyle.IndentCaseLabels = true;1851MozillaStyle.ObjCSpaceAfterProperty = true;1852MozillaStyle.ObjCSpaceBeforeProtocolList = false;1853MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200;1854MozillaStyle.PointerAlignment = FormatStyle::PAS_Left;1855MozillaStyle.SpaceAfterTemplateKeyword = false;1856return MozillaStyle;1857}18581859FormatStyle getWebKitStyle() {1860FormatStyle Style = getLLVMStyle();1861Style.AccessModifierOffset = -4;1862Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;1863Style.AlignOperands = FormatStyle::OAS_DontAlign;1864Style.AlignTrailingComments = {};1865Style.AlignTrailingComments.Kind = FormatStyle::TCAS_Never;1866Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty;1867Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;1868Style.BreakBeforeBraces = FormatStyle::BS_WebKit;1869Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;1870Style.ColumnLimit = 0;1871Style.Cpp11BracedListStyle = false;1872Style.FixNamespaceComments = false;1873Style.IndentWidth = 4;1874Style.NamespaceIndentation = FormatStyle::NI_Inner;1875Style.ObjCBlockIndentWidth = 4;1876Style.ObjCSpaceAfterProperty = true;1877Style.PointerAlignment = FormatStyle::PAS_Left;1878Style.SpaceBeforeCpp11BracedList = true;1879Style.SpaceInEmptyBlock = true;1880return Style;1881}18821883FormatStyle getGNUStyle() {1884FormatStyle Style = getLLVMStyle();1885Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All;1886Style.BreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;1887Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;1888Style.BreakBeforeBraces = FormatStyle::BS_GNU;1889Style.BreakBeforeTernaryOperators = true;1890Style.ColumnLimit = 79;1891Style.Cpp11BracedListStyle = false;1892Style.FixNamespaceComments = false;1893Style.SpaceBeforeParens = FormatStyle::SBPO_Always;1894Style.Standard = FormatStyle::LS_Cpp03;1895return Style;1896}18971898FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language) {1899FormatStyle Style = getLLVMStyle(Language);1900Style.ColumnLimit = 120;1901Style.TabWidth = 4;1902Style.IndentWidth = 4;1903Style.UseTab = FormatStyle::UT_Never;1904Style.BreakBeforeBraces = FormatStyle::BS_Custom;1905Style.BraceWrapping.AfterClass = true;1906Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;1907Style.BraceWrapping.AfterEnum = true;1908Style.BraceWrapping.AfterFunction = true;1909Style.BraceWrapping.AfterNamespace = true;1910Style.BraceWrapping.AfterObjCDeclaration = true;1911Style.BraceWrapping.AfterStruct = true;1912Style.BraceWrapping.AfterExternBlock = true;1913Style.BraceWrapping.BeforeCatch = true;1914Style.BraceWrapping.BeforeElse = true;1915Style.BraceWrapping.BeforeWhile = false;1916Style.PenaltyReturnTypeOnItsOwnLine = 1000;1917Style.AllowShortEnumsOnASingleLine = false;1918Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;1919Style.AllowShortCaseLabelsOnASingleLine = false;1920Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;1921Style.AllowShortLoopsOnASingleLine = false;1922Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;1923Style.BreakAfterReturnType = FormatStyle::RTBS_None;1924return Style;1925}19261927FormatStyle getClangFormatStyle() {1928FormatStyle Style = getLLVMStyle();1929Style.InsertBraces = true;1930Style.InsertNewlineAtEOF = true;1931Style.IntegerLiteralSeparator.Decimal = 3;1932Style.IntegerLiteralSeparator.DecimalMinDigits = 5;1933Style.LineEnding = FormatStyle::LE_LF;1934Style.RemoveBracesLLVM = true;1935Style.RemoveParentheses = FormatStyle::RPS_ReturnStatement;1936Style.RemoveSemicolon = true;1937return Style;1938}19391940FormatStyle getNoStyle() {1941FormatStyle NoStyle = getLLVMStyle();1942NoStyle.DisableFormat = true;1943NoStyle.SortIncludes = FormatStyle::SI_Never;1944NoStyle.SortUsingDeclarations = FormatStyle::SUD_Never;1945return NoStyle;1946}19471948bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language,1949FormatStyle *Style) {1950if (Name.equals_insensitive("llvm"))1951*Style = getLLVMStyle(Language);1952else if (Name.equals_insensitive("chromium"))1953*Style = getChromiumStyle(Language);1954else if (Name.equals_insensitive("mozilla"))1955*Style = getMozillaStyle();1956else if (Name.equals_insensitive("google"))1957*Style = getGoogleStyle(Language);1958else if (Name.equals_insensitive("webkit"))1959*Style = getWebKitStyle();1960else if (Name.equals_insensitive("gnu"))1961*Style = getGNUStyle();1962else if (Name.equals_insensitive("microsoft"))1963*Style = getMicrosoftStyle(Language);1964else if (Name.equals_insensitive("clang-format"))1965*Style = getClangFormatStyle();1966else if (Name.equals_insensitive("none"))1967*Style = getNoStyle();1968else if (Name.equals_insensitive("inheritparentconfig"))1969Style->InheritsParentConfig = true;1970else1971return false;19721973Style->Language = Language;1974return true;1975}19761977ParseError validateQualifierOrder(FormatStyle *Style) {1978// If its empty then it means don't do anything.1979if (Style->QualifierOrder.empty())1980return ParseError::MissingQualifierOrder;19811982// Ensure the list contains only currently valid qualifiers.1983for (const auto &Qualifier : Style->QualifierOrder) {1984if (Qualifier == "type")1985continue;1986auto token =1987LeftRightQualifierAlignmentFixer::getTokenFromQualifier(Qualifier);1988if (token == tok::identifier)1989return ParseError::InvalidQualifierSpecified;1990}19911992// Ensure the list is unique (no duplicates).1993std::set<std::string> UniqueQualifiers(Style->QualifierOrder.begin(),1994Style->QualifierOrder.end());1995if (Style->QualifierOrder.size() != UniqueQualifiers.size()) {1996LLVM_DEBUG(llvm::dbgs()1997<< "Duplicate Qualifiers " << Style->QualifierOrder.size()1998<< " vs " << UniqueQualifiers.size() << "\n");1999return ParseError::DuplicateQualifierSpecified;2000}20012002// Ensure the list has 'type' in it.2003if (!llvm::is_contained(Style->QualifierOrder, "type"))2004return ParseError::MissingQualifierType;20052006return ParseError::Success;2007}20082009std::error_code parseConfiguration(llvm::MemoryBufferRef Config,2010FormatStyle *Style, bool AllowUnknownOptions,2011llvm::SourceMgr::DiagHandlerTy DiagHandler,2012void *DiagHandlerCtxt) {2013assert(Style);2014FormatStyle::LanguageKind Language = Style->Language;2015assert(Language != FormatStyle::LK_None);2016if (Config.getBuffer().trim().empty())2017return make_error_code(ParseError::Success);2018Style->StyleSet.Clear();2019std::vector<FormatStyle> Styles;2020llvm::yaml::Input Input(Config, /*Ctxt=*/nullptr, DiagHandler,2021DiagHandlerCtxt);2022// DocumentListTraits<vector<FormatStyle>> uses the context to get default2023// values for the fields, keys for which are missing from the configuration.2024// Mapping also uses the context to get the language to find the correct2025// base style.2026Input.setContext(Style);2027Input.setAllowUnknownKeys(AllowUnknownOptions);2028Input >> Styles;2029if (Input.error())2030return Input.error();20312032for (unsigned i = 0; i < Styles.size(); ++i) {2033// Ensures that only the first configuration can skip the Language option.2034if (Styles[i].Language == FormatStyle::LK_None && i != 0)2035return make_error_code(ParseError::Error);2036// Ensure that each language is configured at most once.2037for (unsigned j = 0; j < i; ++j) {2038if (Styles[i].Language == Styles[j].Language) {2039LLVM_DEBUG(llvm::dbgs()2040<< "Duplicate languages in the config file on positions "2041<< j << " and " << i << "\n");2042return make_error_code(ParseError::Error);2043}2044}2045}2046// Look for a suitable configuration starting from the end, so we can2047// find the configuration for the specific language first, and the default2048// configuration (which can only be at slot 0) after it.2049FormatStyle::FormatStyleSet StyleSet;2050bool LanguageFound = false;2051for (const FormatStyle &Style : llvm::reverse(Styles)) {2052if (Style.Language != FormatStyle::LK_None)2053StyleSet.Add(Style);2054if (Style.Language == Language)2055LanguageFound = true;2056}2057if (!LanguageFound) {2058if (Styles.empty() || Styles[0].Language != FormatStyle::LK_None)2059return make_error_code(ParseError::Unsuitable);2060FormatStyle DefaultStyle = Styles[0];2061DefaultStyle.Language = Language;2062StyleSet.Add(std::move(DefaultStyle));2063}2064*Style = *StyleSet.Get(Language);2065if (Style->InsertTrailingCommas != FormatStyle::TCS_None &&2066Style->BinPackArguments) {2067// See comment on FormatStyle::TSC_Wrapped.2068return make_error_code(ParseError::BinPackTrailingCommaConflict);2069}2070if (Style->QualifierAlignment != FormatStyle::QAS_Leave)2071return make_error_code(validateQualifierOrder(Style));2072return make_error_code(ParseError::Success);2073}20742075std::string configurationAsText(const FormatStyle &Style) {2076std::string Text;2077llvm::raw_string_ostream Stream(Text);2078llvm::yaml::Output Output(Stream);2079// We use the same mapping method for input and output, so we need a non-const2080// reference here.2081FormatStyle NonConstStyle = Style;2082expandPresetsBraceWrapping(NonConstStyle);2083expandPresetsSpaceBeforeParens(NonConstStyle);2084expandPresetsSpacesInParens(NonConstStyle);2085Output << NonConstStyle;20862087return Stream.str();2088}20892090std::optional<FormatStyle>2091FormatStyle::FormatStyleSet::Get(FormatStyle::LanguageKind Language) const {2092if (!Styles)2093return std::nullopt;2094auto It = Styles->find(Language);2095if (It == Styles->end())2096return std::nullopt;2097FormatStyle Style = It->second;2098Style.StyleSet = *this;2099return Style;2100}21012102void FormatStyle::FormatStyleSet::Add(FormatStyle Style) {2103assert(Style.Language != LK_None &&2104"Cannot add a style for LK_None to a StyleSet");2105assert(2106!Style.StyleSet.Styles &&2107"Cannot add a style associated with an existing StyleSet to a StyleSet");2108if (!Styles)2109Styles = std::make_shared<MapType>();2110(*Styles)[Style.Language] = std::move(Style);2111}21122113void FormatStyle::FormatStyleSet::Clear() { Styles.reset(); }21142115std::optional<FormatStyle>2116FormatStyle::GetLanguageStyle(FormatStyle::LanguageKind Language) const {2117return StyleSet.Get(Language);2118}21192120namespace {21212122class ParensRemover : public TokenAnalyzer {2123public:2124ParensRemover(const Environment &Env, const FormatStyle &Style)2125: TokenAnalyzer(Env, Style) {}21262127std::pair<tooling::Replacements, unsigned>2128analyze(TokenAnnotator &Annotator,2129SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,2130FormatTokenLexer &Tokens) override {2131AffectedRangeMgr.computeAffectedLines(AnnotatedLines);2132tooling::Replacements Result;2133removeParens(AnnotatedLines, Result);2134return {Result, 0};2135}21362137private:2138void removeParens(SmallVectorImpl<AnnotatedLine *> &Lines,2139tooling::Replacements &Result) {2140const auto &SourceMgr = Env.getSourceManager();2141for (auto *Line : Lines) {2142removeParens(Line->Children, Result);2143if (!Line->Affected)2144continue;2145for (const auto *Token = Line->First; Token && !Token->Finalized;2146Token = Token->Next) {2147if (!Token->Optional || !Token->isOneOf(tok::l_paren, tok::r_paren))2148continue;2149auto *Next = Token->Next;2150assert(Next && Next->isNot(tok::eof));2151SourceLocation Start;2152if (Next->NewlinesBefore == 0) {2153Start = Token->Tok.getLocation();2154Next->WhitespaceRange = Token->WhitespaceRange;2155} else {2156Start = Token->WhitespaceRange.getBegin();2157}2158const auto &Range =2159CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());2160cantFail(Result.add(tooling::Replacement(SourceMgr, Range, " ")));2161}2162}2163}2164};21652166class BracesInserter : public TokenAnalyzer {2167public:2168BracesInserter(const Environment &Env, const FormatStyle &Style)2169: TokenAnalyzer(Env, Style) {}21702171std::pair<tooling::Replacements, unsigned>2172analyze(TokenAnnotator &Annotator,2173SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,2174FormatTokenLexer &Tokens) override {2175AffectedRangeMgr.computeAffectedLines(AnnotatedLines);2176tooling::Replacements Result;2177insertBraces(AnnotatedLines, Result);2178return {Result, 0};2179}21802181private:2182void insertBraces(SmallVectorImpl<AnnotatedLine *> &Lines,2183tooling::Replacements &Result) {2184const auto &SourceMgr = Env.getSourceManager();2185int OpeningBraceSurplus = 0;2186for (AnnotatedLine *Line : Lines) {2187insertBraces(Line->Children, Result);2188if (!Line->Affected && OpeningBraceSurplus == 0)2189continue;2190for (FormatToken *Token = Line->First; Token && !Token->Finalized;2191Token = Token->Next) {2192int BraceCount = Token->BraceCount;2193if (BraceCount == 0)2194continue;2195std::string Brace;2196if (BraceCount < 0) {2197assert(BraceCount == -1);2198if (!Line->Affected)2199break;2200Brace = Token->is(tok::comment) ? "\n{" : "{";2201++OpeningBraceSurplus;2202} else {2203if (OpeningBraceSurplus == 0)2204break;2205if (OpeningBraceSurplus < BraceCount)2206BraceCount = OpeningBraceSurplus;2207Brace = '\n' + std::string(BraceCount, '}');2208OpeningBraceSurplus -= BraceCount;2209}2210Token->BraceCount = 0;2211const auto Start = Token->Tok.getEndLoc();2212cantFail(Result.add(tooling::Replacement(SourceMgr, Start, 0, Brace)));2213}2214}2215assert(OpeningBraceSurplus == 0);2216}2217};22182219class BracesRemover : public TokenAnalyzer {2220public:2221BracesRemover(const Environment &Env, const FormatStyle &Style)2222: TokenAnalyzer(Env, Style) {}22232224std::pair<tooling::Replacements, unsigned>2225analyze(TokenAnnotator &Annotator,2226SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,2227FormatTokenLexer &Tokens) override {2228AffectedRangeMgr.computeAffectedLines(AnnotatedLines);2229tooling::Replacements Result;2230removeBraces(AnnotatedLines, Result);2231return {Result, 0};2232}22332234private:2235void removeBraces(SmallVectorImpl<AnnotatedLine *> &Lines,2236tooling::Replacements &Result) {2237const auto &SourceMgr = Env.getSourceManager();2238const auto End = Lines.end();2239for (auto I = Lines.begin(); I != End; ++I) {2240const auto Line = *I;2241removeBraces(Line->Children, Result);2242if (!Line->Affected)2243continue;2244const auto NextLine = I + 1 == End ? nullptr : I[1];2245for (auto Token = Line->First; Token && !Token->Finalized;2246Token = Token->Next) {2247if (!Token->Optional)2248continue;2249if (!Token->isOneOf(tok::l_brace, tok::r_brace))2250continue;2251auto Next = Token->Next;2252assert(Next || Token == Line->Last);2253if (!Next && NextLine)2254Next = NextLine->First;2255SourceLocation Start;2256if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) {2257Start = Token->Tok.getLocation();2258Next->WhitespaceRange = Token->WhitespaceRange;2259} else {2260Start = Token->WhitespaceRange.getBegin();2261}2262const auto Range =2263CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());2264cantFail(Result.add(tooling::Replacement(SourceMgr, Range, "")));2265}2266}2267}2268};22692270class SemiRemover : public TokenAnalyzer {2271public:2272SemiRemover(const Environment &Env, const FormatStyle &Style)2273: TokenAnalyzer(Env, Style) {}22742275std::pair<tooling::Replacements, unsigned>2276analyze(TokenAnnotator &Annotator,2277SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,2278FormatTokenLexer &Tokens) override {2279AffectedRangeMgr.computeAffectedLines(AnnotatedLines);2280tooling::Replacements Result;2281removeSemi(Annotator, AnnotatedLines, Result);2282return {Result, 0};2283}22842285private:2286void removeSemi(TokenAnnotator &Annotator,2287SmallVectorImpl<AnnotatedLine *> &Lines,2288tooling::Replacements &Result) {2289auto PrecededByFunctionRBrace = [](const FormatToken &Tok) {2290const auto *Prev = Tok.Previous;2291if (!Prev || Prev->isNot(tok::r_brace))2292return false;2293const auto *LBrace = Prev->MatchingParen;2294return LBrace && LBrace->is(TT_FunctionLBrace);2295};2296const auto &SourceMgr = Env.getSourceManager();2297const auto End = Lines.end();2298for (auto I = Lines.begin(); I != End; ++I) {2299const auto Line = *I;2300removeSemi(Annotator, Line->Children, Result);2301if (!Line->Affected)2302continue;2303Annotator.calculateFormattingInformation(*Line);2304const auto NextLine = I + 1 == End ? nullptr : I[1];2305for (auto Token = Line->First; Token && !Token->Finalized;2306Token = Token->Next) {2307if (Token->isNot(tok::semi) ||2308(!Token->Optional && !PrecededByFunctionRBrace(*Token))) {2309continue;2310}2311auto Next = Token->Next;2312assert(Next || Token == Line->Last);2313if (!Next && NextLine)2314Next = NextLine->First;2315SourceLocation Start;2316if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) {2317Start = Token->Tok.getLocation();2318Next->WhitespaceRange = Token->WhitespaceRange;2319} else {2320Start = Token->WhitespaceRange.getBegin();2321}2322const auto Range =2323CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());2324cantFail(Result.add(tooling::Replacement(SourceMgr, Range, "")));2325}2326}2327}2328};23292330class JavaScriptRequoter : public TokenAnalyzer {2331public:2332JavaScriptRequoter(const Environment &Env, const FormatStyle &Style)2333: TokenAnalyzer(Env, Style) {}23342335std::pair<tooling::Replacements, unsigned>2336analyze(TokenAnnotator &Annotator,2337SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,2338FormatTokenLexer &Tokens) override {2339AffectedRangeMgr.computeAffectedLines(AnnotatedLines);2340tooling::Replacements Result;2341requoteJSStringLiteral(AnnotatedLines, Result);2342return {Result, 0};2343}23442345private:2346// Replaces double/single-quoted string literal as appropriate, re-escaping2347// the contents in the process.2348void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines,2349tooling::Replacements &Result) {2350for (AnnotatedLine *Line : Lines) {2351requoteJSStringLiteral(Line->Children, Result);2352if (!Line->Affected)2353continue;2354for (FormatToken *FormatTok = Line->First; FormatTok;2355FormatTok = FormatTok->Next) {2356StringRef Input = FormatTok->TokenText;2357if (FormatTok->Finalized || !FormatTok->isStringLiteral() ||2358// NB: testing for not starting with a double quote to avoid2359// breaking `template strings`.2360(Style.JavaScriptQuotes == FormatStyle::JSQS_Single &&2361!Input.starts_with("\"")) ||2362(Style.JavaScriptQuotes == FormatStyle::JSQS_Double &&2363!Input.starts_with("\'"))) {2364continue;2365}23662367// Change start and end quote.2368bool IsSingle = Style.JavaScriptQuotes == FormatStyle::JSQS_Single;2369SourceLocation Start = FormatTok->Tok.getLocation();2370auto Replace = [&](SourceLocation Start, unsigned Length,2371StringRef ReplacementText) {2372auto Err = Result.add(tooling::Replacement(2373Env.getSourceManager(), Start, Length, ReplacementText));2374// FIXME: handle error. For now, print error message and skip the2375// replacement for release version.2376if (Err) {2377llvm::errs() << toString(std::move(Err)) << "\n";2378assert(false);2379}2380};2381Replace(Start, 1, IsSingle ? "'" : "\"");2382Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1,2383IsSingle ? "'" : "\"");23842385// Escape internal quotes.2386bool Escaped = false;2387for (size_t i = 1; i < Input.size() - 1; i++) {2388switch (Input[i]) {2389case '\\':2390if (!Escaped && i + 1 < Input.size() &&2391((IsSingle && Input[i + 1] == '"') ||2392(!IsSingle && Input[i + 1] == '\''))) {2393// Remove this \, it's escaping a " or ' that no longer needs2394// escaping2395Replace(Start.getLocWithOffset(i), 1, "");2396continue;2397}2398Escaped = !Escaped;2399break;2400case '\"':2401case '\'':2402if (!Escaped && IsSingle == (Input[i] == '\'')) {2403// Escape the quote.2404Replace(Start.getLocWithOffset(i), 0, "\\");2405}2406Escaped = false;2407break;2408default:2409Escaped = false;2410break;2411}2412}2413}2414}2415}2416};24172418class Formatter : public TokenAnalyzer {2419public:2420Formatter(const Environment &Env, const FormatStyle &Style,2421FormattingAttemptStatus *Status)2422: TokenAnalyzer(Env, Style), Status(Status) {}24232424std::pair<tooling::Replacements, unsigned>2425analyze(TokenAnnotator &Annotator,2426SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,2427FormatTokenLexer &Tokens) override {2428tooling::Replacements Result;2429deriveLocalStyle(AnnotatedLines);2430AffectedRangeMgr.computeAffectedLines(AnnotatedLines);2431for (AnnotatedLine *Line : AnnotatedLines)2432Annotator.calculateFormattingInformation(*Line);2433Annotator.setCommentLineLevels(AnnotatedLines);24342435WhitespaceManager Whitespaces(2436Env.getSourceManager(), Style,2437Style.LineEnding > FormatStyle::LE_CRLF2438? WhitespaceManager::inputUsesCRLF(2439Env.getSourceManager().getBufferData(Env.getFileID()),2440Style.LineEnding == FormatStyle::LE_DeriveCRLF)2441: Style.LineEnding == FormatStyle::LE_CRLF);2442ContinuationIndenter Indenter(Style, Tokens.getKeywords(),2443Env.getSourceManager(), Whitespaces, Encoding,2444BinPackInconclusiveFunctions);2445unsigned Penalty =2446UnwrappedLineFormatter(&Indenter, &Whitespaces, Style,2447Tokens.getKeywords(), Env.getSourceManager(),2448Status)2449.format(AnnotatedLines, /*DryRun=*/false,2450/*AdditionalIndent=*/0,2451/*FixBadIndentation=*/false,2452/*FirstStartColumn=*/Env.getFirstStartColumn(),2453/*NextStartColumn=*/Env.getNextStartColumn(),2454/*LastStartColumn=*/Env.getLastStartColumn());2455for (const auto &R : Whitespaces.generateReplacements())2456if (Result.add(R))2457return std::make_pair(Result, 0);2458return std::make_pair(Result, Penalty);2459}24602461private:2462bool2463hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine *> &Lines) {2464for (const AnnotatedLine *Line : Lines) {2465if (hasCpp03IncompatibleFormat(Line->Children))2466return true;2467for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) {2468if (!Tok->hasWhitespaceBefore()) {2469if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener))2470return true;2471if (Tok->is(TT_TemplateCloser) &&2472Tok->Previous->is(TT_TemplateCloser)) {2473return true;2474}2475}2476}2477}2478return false;2479}24802481int countVariableAlignments(const SmallVectorImpl<AnnotatedLine *> &Lines) {2482int AlignmentDiff = 0;2483for (const AnnotatedLine *Line : Lines) {2484AlignmentDiff += countVariableAlignments(Line->Children);2485for (FormatToken *Tok = Line->First; Tok && Tok->Next; Tok = Tok->Next) {2486if (Tok->isNot(TT_PointerOrReference))2487continue;2488// Don't treat space in `void foo() &&` as evidence.2489if (const auto *Prev = Tok->getPreviousNonComment()) {2490if (Prev->is(tok::r_paren) && Prev->MatchingParen) {2491if (const auto *Func =2492Prev->MatchingParen->getPreviousNonComment()) {2493if (Func->isOneOf(TT_FunctionDeclarationName, TT_StartOfName,2494TT_OverloadedOperator)) {2495continue;2496}2497}2498}2499}2500bool SpaceBefore = Tok->hasWhitespaceBefore();2501bool SpaceAfter = Tok->Next->hasWhitespaceBefore();2502if (SpaceBefore && !SpaceAfter)2503++AlignmentDiff;2504if (!SpaceBefore && SpaceAfter)2505--AlignmentDiff;2506}2507}2508return AlignmentDiff;2509}25102511void2512deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {2513bool HasBinPackedFunction = false;2514bool HasOnePerLineFunction = false;2515for (AnnotatedLine *Line : AnnotatedLines) {2516if (!Line->First->Next)2517continue;2518FormatToken *Tok = Line->First->Next;2519while (Tok->Next) {2520if (Tok->is(PPK_BinPacked))2521HasBinPackedFunction = true;2522if (Tok->is(PPK_OnePerLine))2523HasOnePerLineFunction = true;25242525Tok = Tok->Next;2526}2527}2528if (Style.DerivePointerAlignment) {2529const auto NetRightCount = countVariableAlignments(AnnotatedLines);2530if (NetRightCount > 0)2531Style.PointerAlignment = FormatStyle::PAS_Right;2532else if (NetRightCount < 0)2533Style.PointerAlignment = FormatStyle::PAS_Left;2534Style.ReferenceAlignment = FormatStyle::RAS_Pointer;2535}2536if (Style.Standard == FormatStyle::LS_Auto) {2537Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines)2538? FormatStyle::LS_Latest2539: FormatStyle::LS_Cpp03;2540}2541BinPackInconclusiveFunctions =2542HasBinPackedFunction || !HasOnePerLineFunction;2543}25442545bool BinPackInconclusiveFunctions;2546FormattingAttemptStatus *Status;2547};25482549/// TrailingCommaInserter inserts trailing commas into container literals.2550/// E.g.:2551/// const x = [2552/// 1,2553/// ];2554/// TrailingCommaInserter runs after formatting. To avoid causing a required2555/// reformatting (and thus reflow), it never inserts a comma that'd exceed the2556/// ColumnLimit.2557///2558/// Because trailing commas disable binpacking of arrays, TrailingCommaInserter2559/// is conceptually incompatible with bin packing.2560class TrailingCommaInserter : public TokenAnalyzer {2561public:2562TrailingCommaInserter(const Environment &Env, const FormatStyle &Style)2563: TokenAnalyzer(Env, Style) {}25642565std::pair<tooling::Replacements, unsigned>2566analyze(TokenAnnotator &Annotator,2567SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,2568FormatTokenLexer &Tokens) override {2569AffectedRangeMgr.computeAffectedLines(AnnotatedLines);2570tooling::Replacements Result;2571insertTrailingCommas(AnnotatedLines, Result);2572return {Result, 0};2573}25742575private:2576/// Inserts trailing commas in [] and {} initializers if they wrap over2577/// multiple lines.2578void insertTrailingCommas(SmallVectorImpl<AnnotatedLine *> &Lines,2579tooling::Replacements &Result) {2580for (AnnotatedLine *Line : Lines) {2581insertTrailingCommas(Line->Children, Result);2582if (!Line->Affected)2583continue;2584for (FormatToken *FormatTok = Line->First; FormatTok;2585FormatTok = FormatTok->Next) {2586if (FormatTok->NewlinesBefore == 0)2587continue;2588FormatToken *Matching = FormatTok->MatchingParen;2589if (!Matching || !FormatTok->getPreviousNonComment())2590continue;2591if (!(FormatTok->is(tok::r_square) &&2592Matching->is(TT_ArrayInitializerLSquare)) &&2593!(FormatTok->is(tok::r_brace) && Matching->is(TT_DictLiteral))) {2594continue;2595}2596FormatToken *Prev = FormatTok->getPreviousNonComment();2597if (Prev->is(tok::comma) || Prev->is(tok::semi))2598continue;2599// getEndLoc is not reliably set during re-lexing, use text length2600// instead.2601SourceLocation Start =2602Prev->Tok.getLocation().getLocWithOffset(Prev->TokenText.size());2603// If inserting a comma would push the code over the column limit, skip2604// this location - it'd introduce an unstable formatting due to the2605// required reflow.2606unsigned ColumnNumber =2607Env.getSourceManager().getSpellingColumnNumber(Start);2608if (ColumnNumber > Style.ColumnLimit)2609continue;2610// Comma insertions cannot conflict with each other, and this pass has a2611// clean set of Replacements, so the operation below cannot fail.2612cantFail(Result.add(2613tooling::Replacement(Env.getSourceManager(), Start, 0, ",")));2614}2615}2616}2617};26182619// This class clean up the erroneous/redundant code around the given ranges in2620// file.2621class Cleaner : public TokenAnalyzer {2622public:2623Cleaner(const Environment &Env, const FormatStyle &Style)2624: TokenAnalyzer(Env, Style),2625DeletedTokens(FormatTokenLess(Env.getSourceManager())) {}26262627// FIXME: eliminate unused parameters.2628std::pair<tooling::Replacements, unsigned>2629analyze(TokenAnnotator &Annotator,2630SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,2631FormatTokenLexer &Tokens) override {2632// FIXME: in the current implementation the granularity of affected range2633// is an annotated line. However, this is not sufficient. Furthermore,2634// redundant code introduced by replacements does not necessarily2635// intercept with ranges of replacements that result in the redundancy.2636// To determine if some redundant code is actually introduced by2637// replacements(e.g. deletions), we need to come up with a more2638// sophisticated way of computing affected ranges.2639AffectedRangeMgr.computeAffectedLines(AnnotatedLines);26402641checkEmptyNamespace(AnnotatedLines);26422643for (auto *Line : AnnotatedLines)2644cleanupLine(Line);26452646return {generateFixes(), 0};2647}26482649private:2650void cleanupLine(AnnotatedLine *Line) {2651for (auto *Child : Line->Children)2652cleanupLine(Child);26532654if (Line->Affected) {2655cleanupRight(Line->First, tok::comma, tok::comma);2656cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma);2657cleanupRight(Line->First, tok::l_paren, tok::comma);2658cleanupLeft(Line->First, tok::comma, tok::r_paren);2659cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace);2660cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace);2661cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal);2662}2663}26642665bool containsOnlyComments(const AnnotatedLine &Line) {2666for (FormatToken *Tok = Line.First; Tok; Tok = Tok->Next)2667if (Tok->isNot(tok::comment))2668return false;2669return true;2670}26712672// Iterate through all lines and remove any empty (nested) namespaces.2673void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {2674std::set<unsigned> DeletedLines;2675for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {2676auto &Line = *AnnotatedLines[i];2677if (Line.startsWithNamespace())2678checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines);2679}26802681for (auto Line : DeletedLines) {2682FormatToken *Tok = AnnotatedLines[Line]->First;2683while (Tok) {2684deleteToken(Tok);2685Tok = Tok->Next;2686}2687}2688}26892690// The function checks if the namespace, which starts from \p CurrentLine, and2691// its nested namespaces are empty and delete them if they are empty. It also2692// sets \p NewLine to the last line checked.2693// Returns true if the current namespace is empty.2694bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,2695unsigned CurrentLine, unsigned &NewLine,2696std::set<unsigned> &DeletedLines) {2697unsigned InitLine = CurrentLine, End = AnnotatedLines.size();2698if (Style.BraceWrapping.AfterNamespace) {2699// If the left brace is in a new line, we should consume it first so that2700// it does not make the namespace non-empty.2701// FIXME: error handling if there is no left brace.2702if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) {2703NewLine = CurrentLine;2704return false;2705}2706} else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) {2707return false;2708}2709while (++CurrentLine < End) {2710if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace))2711break;27122713if (AnnotatedLines[CurrentLine]->startsWithNamespace()) {2714if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine,2715DeletedLines)) {2716return false;2717}2718CurrentLine = NewLine;2719continue;2720}27212722if (containsOnlyComments(*AnnotatedLines[CurrentLine]))2723continue;27242725// If there is anything other than comments or nested namespaces in the2726// current namespace, the namespace cannot be empty.2727NewLine = CurrentLine;2728return false;2729}27302731NewLine = CurrentLine;2732if (CurrentLine >= End)2733return false;27342735// Check if the empty namespace is actually affected by changed ranges.2736if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange(2737AnnotatedLines[InitLine]->First->Tok.getLocation(),2738AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc()))) {2739return false;2740}27412742for (unsigned i = InitLine; i <= CurrentLine; ++i)2743DeletedLines.insert(i);27442745return true;2746}27472748// Checks pairs {start, start->next},..., {end->previous, end} and deletes one2749// of the token in the pair if the left token has \p LK token kind and the2750// right token has \p RK token kind. If \p DeleteLeft is true, the left token2751// is deleted on match; otherwise, the right token is deleted.2752template <typename LeftKind, typename RightKind>2753void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK,2754bool DeleteLeft) {2755auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * {2756for (auto *Res = Tok.Next; Res; Res = Res->Next) {2757if (Res->isNot(tok::comment) &&2758DeletedTokens.find(Res) == DeletedTokens.end()) {2759return Res;2760}2761}2762return nullptr;2763};2764for (auto *Left = Start; Left;) {2765auto *Right = NextNotDeleted(*Left);2766if (!Right)2767break;2768if (Left->is(LK) && Right->is(RK)) {2769deleteToken(DeleteLeft ? Left : Right);2770for (auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next)2771deleteToken(Tok);2772// If the right token is deleted, we should keep the left token2773// unchanged and pair it with the new right token.2774if (!DeleteLeft)2775continue;2776}2777Left = Right;2778}2779}27802781template <typename LeftKind, typename RightKind>2782void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) {2783cleanupPair(Start, LK, RK, /*DeleteLeft=*/true);2784}27852786template <typename LeftKind, typename RightKind>2787void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) {2788cleanupPair(Start, LK, RK, /*DeleteLeft=*/false);2789}27902791// Delete the given token.2792inline void deleteToken(FormatToken *Tok) {2793if (Tok)2794DeletedTokens.insert(Tok);2795}27962797tooling::Replacements generateFixes() {2798tooling::Replacements Fixes;2799SmallVector<FormatToken *> Tokens;2800std::copy(DeletedTokens.begin(), DeletedTokens.end(),2801std::back_inserter(Tokens));28022803// Merge multiple continuous token deletions into one big deletion so that2804// the number of replacements can be reduced. This makes computing affected2805// ranges more efficient when we run reformat on the changed code.2806unsigned Idx = 0;2807while (Idx < Tokens.size()) {2808unsigned St = Idx, End = Idx;2809while ((End + 1) < Tokens.size() && Tokens[End]->Next == Tokens[End + 1])2810++End;2811auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(),2812Tokens[End]->Tok.getEndLoc());2813auto Err =2814Fixes.add(tooling::Replacement(Env.getSourceManager(), SR, ""));2815// FIXME: better error handling. for now just print error message and skip2816// for the release version.2817if (Err) {2818llvm::errs() << toString(std::move(Err)) << "\n";2819assert(false && "Fixes must not conflict!");2820}2821Idx = End + 1;2822}28232824return Fixes;2825}28262827// Class for less-than inequality comparason for the set `RedundantTokens`.2828// We store tokens in the order they appear in the translation unit so that2829// we do not need to sort them in `generateFixes()`.2830struct FormatTokenLess {2831FormatTokenLess(const SourceManager &SM) : SM(SM) {}28322833bool operator()(const FormatToken *LHS, const FormatToken *RHS) const {2834return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(),2835RHS->Tok.getLocation());2836}2837const SourceManager &SM;2838};28392840// Tokens to be deleted.2841std::set<FormatToken *, FormatTokenLess> DeletedTokens;2842};28432844class ObjCHeaderStyleGuesser : public TokenAnalyzer {2845public:2846ObjCHeaderStyleGuesser(const Environment &Env, const FormatStyle &Style)2847: TokenAnalyzer(Env, Style), IsObjC(false) {}28482849std::pair<tooling::Replacements, unsigned>2850analyze(TokenAnnotator &Annotator,2851SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,2852FormatTokenLexer &Tokens) override {2853assert(Style.Language == FormatStyle::LK_Cpp);2854IsObjC = guessIsObjC(Env.getSourceManager(), AnnotatedLines,2855Tokens.getKeywords());2856tooling::Replacements Result;2857return {Result, 0};2858}28592860bool isObjC() { return IsObjC; }28612862private:2863static bool2864guessIsObjC(const SourceManager &SourceManager,2865const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,2866const AdditionalKeywords &Keywords) {2867// Keep this array sorted, since we are binary searching over it.2868static constexpr llvm::StringLiteral FoundationIdentifiers[] = {2869"CGFloat",2870"CGPoint",2871"CGPointMake",2872"CGPointZero",2873"CGRect",2874"CGRectEdge",2875"CGRectInfinite",2876"CGRectMake",2877"CGRectNull",2878"CGRectZero",2879"CGSize",2880"CGSizeMake",2881"CGVector",2882"CGVectorMake",2883"FOUNDATION_EXPORT", // This is an alias for FOUNDATION_EXTERN.2884"FOUNDATION_EXTERN",2885"NSAffineTransform",2886"NSArray",2887"NSAttributedString",2888"NSBlockOperation",2889"NSBundle",2890"NSCache",2891"NSCalendar",2892"NSCharacterSet",2893"NSCountedSet",2894"NSData",2895"NSDataDetector",2896"NSDecimal",2897"NSDecimalNumber",2898"NSDictionary",2899"NSEdgeInsets",2900"NSError",2901"NSErrorDomain",2902"NSHashTable",2903"NSIndexPath",2904"NSIndexSet",2905"NSInteger",2906"NSInvocationOperation",2907"NSLocale",2908"NSMapTable",2909"NSMutableArray",2910"NSMutableAttributedString",2911"NSMutableCharacterSet",2912"NSMutableData",2913"NSMutableDictionary",2914"NSMutableIndexSet",2915"NSMutableOrderedSet",2916"NSMutableSet",2917"NSMutableString",2918"NSNumber",2919"NSNumberFormatter",2920"NSObject",2921"NSOperation",2922"NSOperationQueue",2923"NSOperationQueuePriority",2924"NSOrderedSet",2925"NSPoint",2926"NSPointerArray",2927"NSQualityOfService",2928"NSRange",2929"NSRect",2930"NSRegularExpression",2931"NSSet",2932"NSSize",2933"NSString",2934"NSTimeZone",2935"NSUInteger",2936"NSURL",2937"NSURLComponents",2938"NSURLQueryItem",2939"NSUUID",2940"NSValue",2941"NS_ASSUME_NONNULL_BEGIN",2942"UIImage",2943"UIView",2944};29452946for (auto *Line : AnnotatedLines) {2947if (Line->First && (Line->First->TokenText.starts_with("#") ||2948Line->First->TokenText == "__pragma" ||2949Line->First->TokenText == "_Pragma")) {2950continue;2951}2952for (const FormatToken *FormatTok = Line->First; FormatTok;2953FormatTok = FormatTok->Next) {2954if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) &&2955(FormatTok->Tok.getObjCKeywordID() != tok::objc_not_keyword ||2956FormatTok->isOneOf(tok::numeric_constant, tok::l_square,2957tok::l_brace))) ||2958(FormatTok->Tok.isAnyIdentifier() &&2959std::binary_search(std::begin(FoundationIdentifiers),2960std::end(FoundationIdentifiers),2961FormatTok->TokenText)) ||2962FormatTok->is(TT_ObjCStringLiteral) ||2963FormatTok->isOneOf(Keywords.kw_NS_CLOSED_ENUM, Keywords.kw_NS_ENUM,2964Keywords.kw_NS_ERROR_ENUM,2965Keywords.kw_NS_OPTIONS, TT_ObjCBlockLBrace,2966TT_ObjCBlockLParen, TT_ObjCDecl, TT_ObjCForIn,2967TT_ObjCMethodExpr, TT_ObjCMethodSpecifier,2968TT_ObjCProperty)) {2969LLVM_DEBUG(llvm::dbgs()2970<< "Detected ObjC at location "2971<< FormatTok->Tok.getLocation().printToString(2972SourceManager)2973<< " token: " << FormatTok->TokenText << " token type: "2974<< getTokenTypeName(FormatTok->getType()) << "\n");2975return true;2976}2977}2978if (guessIsObjC(SourceManager, Line->Children, Keywords))2979return true;2980}2981return false;2982}29832984bool IsObjC;2985};29862987struct IncludeDirective {2988StringRef Filename;2989StringRef Text;2990unsigned Offset;2991int Category;2992int Priority;2993};29942995struct JavaImportDirective {2996StringRef Identifier;2997StringRef Text;2998unsigned Offset;2999SmallVector<StringRef> AssociatedCommentLines;3000bool IsStatic;3001};30023003} // end anonymous namespace30043005// Determines whether 'Ranges' intersects with ('Start', 'End').3006static bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start,3007unsigned End) {3008for (const auto &Range : Ranges) {3009if (Range.getOffset() < End &&3010Range.getOffset() + Range.getLength() > Start) {3011return true;3012}3013}3014return false;3015}30163017// Returns a pair (Index, OffsetToEOL) describing the position of the cursor3018// before sorting/deduplicating. Index is the index of the include under the3019// cursor in the original set of includes. If this include has duplicates, it is3020// the index of the first of the duplicates as the others are going to be3021// removed. OffsetToEOL describes the cursor's position relative to the end of3022// its current line.3023// If `Cursor` is not on any #include, `Index` will be UINT_MAX.3024static std::pair<unsigned, unsigned>3025FindCursorIndex(const SmallVectorImpl<IncludeDirective> &Includes,3026const SmallVectorImpl<unsigned> &Indices, unsigned Cursor) {3027unsigned CursorIndex = UINT_MAX;3028unsigned OffsetToEOL = 0;3029for (int i = 0, e = Includes.size(); i != e; ++i) {3030unsigned Start = Includes[Indices[i]].Offset;3031unsigned End = Start + Includes[Indices[i]].Text.size();3032if (!(Cursor >= Start && Cursor < End))3033continue;3034CursorIndex = Indices[i];3035OffsetToEOL = End - Cursor;3036// Put the cursor on the only remaining #include among the duplicate3037// #includes.3038while (--i >= 0 && Includes[CursorIndex].Text == Includes[Indices[i]].Text)3039CursorIndex = i;3040break;3041}3042return std::make_pair(CursorIndex, OffsetToEOL);3043}30443045// Replace all "\r\n" with "\n".3046std::string replaceCRLF(const std::string &Code) {3047std::string NewCode;3048size_t Pos = 0, LastPos = 0;30493050do {3051Pos = Code.find("\r\n", LastPos);3052if (Pos == LastPos) {3053++LastPos;3054continue;3055}3056if (Pos == std::string::npos) {3057NewCode += Code.substr(LastPos);3058break;3059}3060NewCode += Code.substr(LastPos, Pos - LastPos) + "\n";3061LastPos = Pos + 2;3062} while (Pos != std::string::npos);30633064return NewCode;3065}30663067// Sorts and deduplicate a block of includes given by 'Includes' alphabetically3068// adding the necessary replacement to 'Replaces'. 'Includes' must be in strict3069// source order.3070// #include directives with the same text will be deduplicated, and only the3071// first #include in the duplicate #includes remains. If the `Cursor` is3072// provided and put on a deleted #include, it will be moved to the remaining3073// #include in the duplicate #includes.3074static void sortCppIncludes(const FormatStyle &Style,3075const SmallVectorImpl<IncludeDirective> &Includes,3076ArrayRef<tooling::Range> Ranges, StringRef FileName,3077StringRef Code, tooling::Replacements &Replaces,3078unsigned *Cursor) {3079tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName);3080const unsigned IncludesBeginOffset = Includes.front().Offset;3081const unsigned IncludesEndOffset =3082Includes.back().Offset + Includes.back().Text.size();3083const unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset;3084if (!affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset))3085return;3086SmallVector<unsigned, 16> Indices =3087llvm::to_vector<16>(llvm::seq<unsigned>(0, Includes.size()));30883089if (Style.SortIncludes == FormatStyle::SI_CaseInsensitive) {3090stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {3091const auto LHSFilenameLower = Includes[LHSI].Filename.lower();3092const auto RHSFilenameLower = Includes[RHSI].Filename.lower();3093return std::tie(Includes[LHSI].Priority, LHSFilenameLower,3094Includes[LHSI].Filename) <3095std::tie(Includes[RHSI].Priority, RHSFilenameLower,3096Includes[RHSI].Filename);3097});3098} else {3099stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {3100return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) <3101std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename);3102});3103}31043105// The index of the include on which the cursor will be put after3106// sorting/deduplicating.3107unsigned CursorIndex;3108// The offset from cursor to the end of line.3109unsigned CursorToEOLOffset;3110if (Cursor) {3111std::tie(CursorIndex, CursorToEOLOffset) =3112FindCursorIndex(Includes, Indices, *Cursor);3113}31143115// Deduplicate #includes.3116Indices.erase(std::unique(Indices.begin(), Indices.end(),3117[&](unsigned LHSI, unsigned RHSI) {3118return Includes[LHSI].Text.trim() ==3119Includes[RHSI].Text.trim();3120}),3121Indices.end());31223123int CurrentCategory = Includes.front().Category;31243125// If the #includes are out of order, we generate a single replacement fixing3126// the entire block. Otherwise, no replacement is generated.3127// In case Style.IncldueStyle.IncludeBlocks != IBS_Preserve, this check is not3128// enough as additional newlines might be added or removed across #include3129// blocks. This we handle below by generating the updated #include blocks and3130// comparing it to the original.3131if (Indices.size() == Includes.size() && is_sorted(Indices) &&3132Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Preserve) {3133return;3134}31353136const auto OldCursor = Cursor ? *Cursor : 0;3137std::string result;3138for (unsigned Index : Indices) {3139if (!result.empty()) {3140result += "\n";3141if (Style.IncludeStyle.IncludeBlocks ==3142tooling::IncludeStyle::IBS_Regroup &&3143CurrentCategory != Includes[Index].Category) {3144result += "\n";3145}3146}3147result += Includes[Index].Text;3148if (Cursor && CursorIndex == Index)3149*Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset;3150CurrentCategory = Includes[Index].Category;3151}31523153if (Cursor && *Cursor >= IncludesEndOffset)3154*Cursor += result.size() - IncludesBlockSize;31553156// If the #includes are out of order, we generate a single replacement fixing3157// the entire range of blocks. Otherwise, no replacement is generated.3158if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr(3159IncludesBeginOffset, IncludesBlockSize)))) {3160if (Cursor)3161*Cursor = OldCursor;3162return;3163}31643165auto Err = Replaces.add(tooling::Replacement(3166FileName, Includes.front().Offset, IncludesBlockSize, result));3167// FIXME: better error handling. For now, just skip the replacement for the3168// release version.3169if (Err) {3170llvm::errs() << toString(std::move(Err)) << "\n";3171assert(false);3172}3173}31743175tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,3176ArrayRef<tooling::Range> Ranges,3177StringRef FileName,3178tooling::Replacements &Replaces,3179unsigned *Cursor) {3180unsigned Prev = llvm::StringSwitch<size_t>(Code)3181.StartsWith("\xEF\xBB\xBF", 3) // UTF-8 BOM3182.Default(0);3183unsigned SearchFrom = 0;3184SmallVector<StringRef, 4> Matches;3185SmallVector<IncludeDirective, 16> IncludesInBlock;31863187// In compiled files, consider the first #include to be the main #include of3188// the file if it is not a system #include. This ensures that the header3189// doesn't have hidden dependencies3190// (http://llvm.org/docs/CodingStandards.html#include-style).3191//3192// FIXME: Do some validation, e.g. edit distance of the base name, to fix3193// cases where the first #include is unlikely to be the main header.3194tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName);3195bool FirstIncludeBlock = true;3196bool MainIncludeFound = false;3197bool FormattingOff = false;31983199// '[' must be the first and '-' the last character inside [...].3200llvm::Regex RawStringRegex(3201"R\"([][A-Za-z0-9_{}#<>%:;.?*+/^&\\$|~!=,'-]*)\\(");3202SmallVector<StringRef, 2> RawStringMatches;3203std::string RawStringTermination = ")\"";32043205for (;;) {3206auto Pos = Code.find('\n', SearchFrom);3207StringRef Line =3208Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);32093210StringRef Trimmed = Line.trim();32113212// #includes inside raw string literals need to be ignored.3213// or we will sort the contents of the string.3214// Skip past until we think we are at the rawstring literal close.3215if (RawStringRegex.match(Trimmed, &RawStringMatches)) {3216std::string CharSequence = RawStringMatches[1].str();3217RawStringTermination = ")" + CharSequence + "\"";3218FormattingOff = true;3219}32203221if (Trimmed.contains(RawStringTermination))3222FormattingOff = false;32233224bool IsBlockComment = false;32253226if (isClangFormatOff(Trimmed)) {3227FormattingOff = true;3228} else if (isClangFormatOn(Trimmed)) {3229FormattingOff = false;3230} else if (Trimmed.starts_with("/*")) {3231IsBlockComment = true;3232Pos = Code.find("*/", SearchFrom + 2);3233}32343235const bool EmptyLineSkipped =3236Trimmed.empty() &&3237(Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Merge ||3238Style.IncludeStyle.IncludeBlocks ==3239tooling::IncludeStyle::IBS_Regroup);32403241bool MergeWithNextLine = Trimmed.ends_with("\\");3242if (!FormattingOff && !MergeWithNextLine) {3243if (!IsBlockComment &&3244tooling::HeaderIncludes::IncludeRegex.match(Trimmed, &Matches)) {3245StringRef IncludeName = Matches[2];3246if (Trimmed.contains("/*") && !Trimmed.contains("*/")) {3247// #include with a start of a block comment, but without the end.3248// Need to keep all the lines until the end of the comment together.3249// FIXME: This is somehow simplified check that probably does not work3250// correctly if there are multiple comments on a line.3251Pos = Code.find("*/", SearchFrom);3252Line = Code.substr(3253Prev, (Pos != StringRef::npos ? Pos + 2 : Code.size()) - Prev);3254}3255int Category = Categories.getIncludePriority(3256IncludeName,3257/*CheckMainHeader=*/!MainIncludeFound && FirstIncludeBlock);3258int Priority = Categories.getSortIncludePriority(3259IncludeName, !MainIncludeFound && FirstIncludeBlock);3260if (Category == 0)3261MainIncludeFound = true;3262IncludesInBlock.push_back(3263{IncludeName, Line, Prev, Category, Priority});3264} else if (!IncludesInBlock.empty() && !EmptyLineSkipped) {3265sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code,3266Replaces, Cursor);3267IncludesInBlock.clear();3268if (Trimmed.starts_with("#pragma hdrstop")) // Precompiled headers.3269FirstIncludeBlock = true;3270else3271FirstIncludeBlock = false;3272}3273}3274if (Pos == StringRef::npos || Pos + 1 == Code.size())3275break;32763277if (!MergeWithNextLine)3278Prev = Pos + 1;3279SearchFrom = Pos + 1;3280}3281if (!IncludesInBlock.empty()) {3282sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, Replaces,3283Cursor);3284}3285return Replaces;3286}32873288// Returns group number to use as a first order sort on imports. Gives UINT_MAX3289// if the import does not match any given groups.3290static unsigned findJavaImportGroup(const FormatStyle &Style,3291StringRef ImportIdentifier) {3292unsigned LongestMatchIndex = UINT_MAX;3293unsigned LongestMatchLength = 0;3294for (unsigned I = 0; I < Style.JavaImportGroups.size(); I++) {3295const std::string &GroupPrefix = Style.JavaImportGroups[I];3296if (ImportIdentifier.starts_with(GroupPrefix) &&3297GroupPrefix.length() > LongestMatchLength) {3298LongestMatchIndex = I;3299LongestMatchLength = GroupPrefix.length();3300}3301}3302return LongestMatchIndex;3303}33043305// Sorts and deduplicates a block of includes given by 'Imports' based on3306// JavaImportGroups, then adding the necessary replacement to 'Replaces'.3307// Import declarations with the same text will be deduplicated. Between each3308// import group, a newline is inserted, and within each import group, a3309// lexicographic sort based on ASCII value is performed.3310static void sortJavaImports(const FormatStyle &Style,3311const SmallVectorImpl<JavaImportDirective> &Imports,3312ArrayRef<tooling::Range> Ranges, StringRef FileName,3313StringRef Code, tooling::Replacements &Replaces) {3314unsigned ImportsBeginOffset = Imports.front().Offset;3315unsigned ImportsEndOffset =3316Imports.back().Offset + Imports.back().Text.size();3317unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset;3318if (!affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset))3319return;33203321SmallVector<unsigned, 16> Indices =3322llvm::to_vector<16>(llvm::seq<unsigned>(0, Imports.size()));3323SmallVector<unsigned, 16> JavaImportGroups;3324JavaImportGroups.reserve(Imports.size());3325for (const JavaImportDirective &Import : Imports)3326JavaImportGroups.push_back(findJavaImportGroup(Style, Import.Identifier));33273328bool StaticImportAfterNormalImport =3329Style.SortJavaStaticImport == FormatStyle::SJSIO_After;3330sort(Indices, [&](unsigned LHSI, unsigned RHSI) {3331// Negating IsStatic to push static imports above non-static imports.3332return std::make_tuple(!Imports[LHSI].IsStatic ^3333StaticImportAfterNormalImport,3334JavaImportGroups[LHSI], Imports[LHSI].Identifier) <3335std::make_tuple(!Imports[RHSI].IsStatic ^3336StaticImportAfterNormalImport,3337JavaImportGroups[RHSI], Imports[RHSI].Identifier);3338});33393340// Deduplicate imports.3341Indices.erase(std::unique(Indices.begin(), Indices.end(),3342[&](unsigned LHSI, unsigned RHSI) {3343return Imports[LHSI].Text == Imports[RHSI].Text;3344}),3345Indices.end());33463347bool CurrentIsStatic = Imports[Indices.front()].IsStatic;3348unsigned CurrentImportGroup = JavaImportGroups[Indices.front()];33493350std::string result;3351for (unsigned Index : Indices) {3352if (!result.empty()) {3353result += "\n";3354if (CurrentIsStatic != Imports[Index].IsStatic ||3355CurrentImportGroup != JavaImportGroups[Index]) {3356result += "\n";3357}3358}3359for (StringRef CommentLine : Imports[Index].AssociatedCommentLines) {3360result += CommentLine;3361result += "\n";3362}3363result += Imports[Index].Text;3364CurrentIsStatic = Imports[Index].IsStatic;3365CurrentImportGroup = JavaImportGroups[Index];3366}33673368// If the imports are out of order, we generate a single replacement fixing3369// the entire block. Otherwise, no replacement is generated.3370if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr(3371Imports.front().Offset, ImportsBlockSize)))) {3372return;3373}33743375auto Err = Replaces.add(tooling::Replacement(FileName, Imports.front().Offset,3376ImportsBlockSize, result));3377// FIXME: better error handling. For now, just skip the replacement for the3378// release version.3379if (Err) {3380llvm::errs() << toString(std::move(Err)) << "\n";3381assert(false);3382}3383}33843385namespace {33863387const char JavaImportRegexPattern[] =3388"^[\t ]*import[\t ]+(static[\t ]*)?([^\t ]*)[\t ]*;";33893390} // anonymous namespace33913392tooling::Replacements sortJavaImports(const FormatStyle &Style, StringRef Code,3393ArrayRef<tooling::Range> Ranges,3394StringRef FileName,3395tooling::Replacements &Replaces) {3396unsigned Prev = 0;3397unsigned SearchFrom = 0;3398llvm::Regex ImportRegex(JavaImportRegexPattern);3399SmallVector<StringRef, 4> Matches;3400SmallVector<JavaImportDirective, 16> ImportsInBlock;3401SmallVector<StringRef> AssociatedCommentLines;34023403bool FormattingOff = false;34043405for (;;) {3406auto Pos = Code.find('\n', SearchFrom);3407StringRef Line =3408Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);34093410StringRef Trimmed = Line.trim();3411if (isClangFormatOff(Trimmed))3412FormattingOff = true;3413else if (isClangFormatOn(Trimmed))3414FormattingOff = false;34153416if (ImportRegex.match(Line, &Matches)) {3417if (FormattingOff) {3418// If at least one import line has formatting turned off, turn off3419// formatting entirely.3420return Replaces;3421}3422StringRef Static = Matches[1];3423StringRef Identifier = Matches[2];3424bool IsStatic = false;3425if (Static.contains("static"))3426IsStatic = true;3427ImportsInBlock.push_back(3428{Identifier, Line, Prev, AssociatedCommentLines, IsStatic});3429AssociatedCommentLines.clear();3430} else if (Trimmed.size() > 0 && !ImportsInBlock.empty()) {3431// Associating comments within the imports with the nearest import below3432AssociatedCommentLines.push_back(Line);3433}3434Prev = Pos + 1;3435if (Pos == StringRef::npos || Pos + 1 == Code.size())3436break;3437SearchFrom = Pos + 1;3438}3439if (!ImportsInBlock.empty())3440sortJavaImports(Style, ImportsInBlock, Ranges, FileName, Code, Replaces);3441return Replaces;3442}34433444bool isMpegTS(StringRef Code) {3445// MPEG transport streams use the ".ts" file extension. clang-format should3446// not attempt to format those. MPEG TS' frame format starts with 0x47 every3447// 189 bytes - detect that and return.3448return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47;3449}34503451bool isLikelyXml(StringRef Code) { return Code.ltrim().starts_with("<"); }34523453tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code,3454ArrayRef<tooling::Range> Ranges,3455StringRef FileName, unsigned *Cursor) {3456tooling::Replacements Replaces;3457if (!Style.SortIncludes || Style.DisableFormat)3458return Replaces;3459if (isLikelyXml(Code))3460return Replaces;3461if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript &&3462isMpegTS(Code)) {3463return Replaces;3464}3465if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript)3466return sortJavaScriptImports(Style, Code, Ranges, FileName);3467if (Style.Language == FormatStyle::LanguageKind::LK_Java)3468return sortJavaImports(Style, Code, Ranges, FileName, Replaces);3469sortCppIncludes(Style, Code, Ranges, FileName, Replaces, Cursor);3470return Replaces;3471}34723473template <typename T>3474static Expected<tooling::Replacements>3475processReplacements(T ProcessFunc, StringRef Code,3476const tooling::Replacements &Replaces,3477const FormatStyle &Style) {3478if (Replaces.empty())3479return tooling::Replacements();34803481auto NewCode = applyAllReplacements(Code, Replaces);3482if (!NewCode)3483return NewCode.takeError();3484std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges();3485StringRef FileName = Replaces.begin()->getFilePath();34863487tooling::Replacements FormatReplaces =3488ProcessFunc(Style, *NewCode, ChangedRanges, FileName);34893490return Replaces.merge(FormatReplaces);3491}34923493Expected<tooling::Replacements>3494formatReplacements(StringRef Code, const tooling::Replacements &Replaces,3495const FormatStyle &Style) {3496// We need to use lambda function here since there are two versions of3497// `sortIncludes`.3498auto SortIncludes = [](const FormatStyle &Style, StringRef Code,3499std::vector<tooling::Range> Ranges,3500StringRef FileName) -> tooling::Replacements {3501return sortIncludes(Style, Code, Ranges, FileName);3502};3503auto SortedReplaces =3504processReplacements(SortIncludes, Code, Replaces, Style);3505if (!SortedReplaces)3506return SortedReplaces.takeError();35073508// We need to use lambda function here since there are two versions of3509// `reformat`.3510auto Reformat = [](const FormatStyle &Style, StringRef Code,3511std::vector<tooling::Range> Ranges,3512StringRef FileName) -> tooling::Replacements {3513return reformat(Style, Code, Ranges, FileName);3514};3515return processReplacements(Reformat, Code, *SortedReplaces, Style);3516}35173518namespace {35193520inline bool isHeaderInsertion(const tooling::Replacement &Replace) {3521return Replace.getOffset() == UINT_MAX && Replace.getLength() == 0 &&3522tooling::HeaderIncludes::IncludeRegex.match(3523Replace.getReplacementText());3524}35253526inline bool isHeaderDeletion(const tooling::Replacement &Replace) {3527return Replace.getOffset() == UINT_MAX && Replace.getLength() == 1;3528}35293530// FIXME: insert empty lines between newly created blocks.3531tooling::Replacements3532fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,3533const FormatStyle &Style) {3534if (!Style.isCpp())3535return Replaces;35363537tooling::Replacements HeaderInsertions;3538std::set<StringRef> HeadersToDelete;3539tooling::Replacements Result;3540for (const auto &R : Replaces) {3541if (isHeaderInsertion(R)) {3542// Replacements from \p Replaces must be conflict-free already, so we can3543// simply consume the error.3544consumeError(HeaderInsertions.add(R));3545} else if (isHeaderDeletion(R)) {3546HeadersToDelete.insert(R.getReplacementText());3547} else if (R.getOffset() == UINT_MAX) {3548llvm::errs() << "Insertions other than header #include insertion are "3549"not supported! "3550<< R.getReplacementText() << "\n";3551} else {3552consumeError(Result.add(R));3553}3554}3555if (HeaderInsertions.empty() && HeadersToDelete.empty())3556return Replaces;35573558StringRef FileName = Replaces.begin()->getFilePath();3559tooling::HeaderIncludes Includes(FileName, Code, Style.IncludeStyle);35603561for (const auto &Header : HeadersToDelete) {3562tooling::Replacements Replaces =3563Includes.remove(Header.trim("\"<>"), Header.starts_with("<"));3564for (const auto &R : Replaces) {3565auto Err = Result.add(R);3566if (Err) {3567// Ignore the deletion on conflict.3568llvm::errs() << "Failed to add header deletion replacement for "3569<< Header << ": " << toString(std::move(Err)) << "\n";3570}3571}3572}35733574SmallVector<StringRef, 4> Matches;3575for (const auto &R : HeaderInsertions) {3576auto IncludeDirective = R.getReplacementText();3577bool Matched =3578tooling::HeaderIncludes::IncludeRegex.match(IncludeDirective, &Matches);3579assert(Matched && "Header insertion replacement must have replacement text "3580"'#include ...'");3581(void)Matched;3582auto IncludeName = Matches[2];3583auto Replace =3584Includes.insert(IncludeName.trim("\"<>"), IncludeName.starts_with("<"),3585tooling::IncludeDirective::Include);3586if (Replace) {3587auto Err = Result.add(*Replace);3588if (Err) {3589consumeError(std::move(Err));3590unsigned NewOffset =3591Result.getShiftedCodePosition(Replace->getOffset());3592auto Shifted = tooling::Replacement(FileName, NewOffset, 0,3593Replace->getReplacementText());3594Result = Result.merge(tooling::Replacements(Shifted));3595}3596}3597}3598return Result;3599}36003601} // anonymous namespace36023603Expected<tooling::Replacements>3604cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces,3605const FormatStyle &Style) {3606// We need to use lambda function here since there are two versions of3607// `cleanup`.3608auto Cleanup = [](const FormatStyle &Style, StringRef Code,3609ArrayRef<tooling::Range> Ranges,3610StringRef FileName) -> tooling::Replacements {3611return cleanup(Style, Code, Ranges, FileName);3612};3613// Make header insertion replacements insert new headers into correct blocks.3614tooling::Replacements NewReplaces =3615fixCppIncludeInsertions(Code, Replaces, Style);3616return cantFail(processReplacements(Cleanup, Code, NewReplaces, Style));3617}36183619namespace internal {3620std::pair<tooling::Replacements, unsigned>3621reformat(const FormatStyle &Style, StringRef Code,3622ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn,3623unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName,3624FormattingAttemptStatus *Status) {3625FormatStyle Expanded = Style;3626expandPresetsBraceWrapping(Expanded);3627expandPresetsSpaceBeforeParens(Expanded);3628expandPresetsSpacesInParens(Expanded);3629Expanded.InsertBraces = false;3630Expanded.RemoveBracesLLVM = false;3631Expanded.RemoveParentheses = FormatStyle::RPS_Leave;3632Expanded.RemoveSemicolon = false;3633switch (Expanded.RequiresClausePosition) {3634case FormatStyle::RCPS_SingleLine:3635case FormatStyle::RCPS_WithPreceding:3636Expanded.IndentRequiresClause = false;3637break;3638default:3639break;3640}36413642if (Expanded.DisableFormat)3643return {tooling::Replacements(), 0};3644if (isLikelyXml(Code))3645return {tooling::Replacements(), 0};3646if (Expanded.Language == FormatStyle::LK_JavaScript && isMpegTS(Code))3647return {tooling::Replacements(), 0};36483649// JSON only needs the formatting passing.3650if (Style.isJson()) {3651std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));3652auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn,3653NextStartColumn, LastStartColumn);3654if (!Env)3655return {};3656// Perform the actual formatting pass.3657tooling::Replacements Replaces =3658Formatter(*Env, Style, Status).process().first;3659// add a replacement to remove the "x = " from the result.3660Replaces = Replaces.merge(3661tooling::Replacements(tooling::Replacement(FileName, 0, 4, "")));3662// apply the reformatting changes and the removal of "x = ".3663if (applyAllReplacements(Code, Replaces))3664return {Replaces, 0};3665return {tooling::Replacements(), 0};3666}36673668auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn,3669NextStartColumn, LastStartColumn);3670if (!Env)3671return {};36723673typedef std::function<std::pair<tooling::Replacements, unsigned>(3674const Environment &)>3675AnalyzerPass;36763677SmallVector<AnalyzerPass, 16> Passes;36783679Passes.emplace_back([&](const Environment &Env) {3680return IntegerLiteralSeparatorFixer().process(Env, Expanded);3681});36823683if (Style.isCpp()) {3684if (Style.QualifierAlignment != FormatStyle::QAS_Leave)3685addQualifierAlignmentFixerPasses(Expanded, Passes);36863687if (Style.RemoveParentheses != FormatStyle::RPS_Leave) {3688FormatStyle S = Expanded;3689S.RemoveParentheses = Style.RemoveParentheses;3690Passes.emplace_back([&, S = std::move(S)](const Environment &Env) {3691return ParensRemover(Env, S).process(/*SkipAnnotation=*/true);3692});3693}36943695if (Style.InsertBraces) {3696FormatStyle S = Expanded;3697S.InsertBraces = true;3698Passes.emplace_back([&, S = std::move(S)](const Environment &Env) {3699return BracesInserter(Env, S).process(/*SkipAnnotation=*/true);3700});3701}37023703if (Style.RemoveBracesLLVM) {3704FormatStyle S = Expanded;3705S.RemoveBracesLLVM = true;3706Passes.emplace_back([&, S = std::move(S)](const Environment &Env) {3707return BracesRemover(Env, S).process(/*SkipAnnotation=*/true);3708});3709}37103711if (Style.RemoveSemicolon) {3712FormatStyle S = Expanded;3713S.RemoveSemicolon = true;3714Passes.emplace_back([&, S = std::move(S)](const Environment &Env) {3715return SemiRemover(Env, S).process();3716});3717}37183719if (Style.FixNamespaceComments) {3720Passes.emplace_back([&](const Environment &Env) {3721return NamespaceEndCommentsFixer(Env, Expanded).process();3722});3723}37243725if (Style.SortUsingDeclarations != FormatStyle::SUD_Never) {3726Passes.emplace_back([&](const Environment &Env) {3727return UsingDeclarationsSorter(Env, Expanded).process();3728});3729}3730}37313732if (Style.SeparateDefinitionBlocks != FormatStyle::SDS_Leave) {3733Passes.emplace_back([&](const Environment &Env) {3734return DefinitionBlockSeparator(Env, Expanded).process();3735});3736}37373738if (Style.Language == FormatStyle::LK_ObjC &&3739!Style.ObjCPropertyAttributeOrder.empty()) {3740Passes.emplace_back([&](const Environment &Env) {3741return ObjCPropertyAttributeOrderFixer(Env, Expanded).process();3742});3743}37443745if (Style.isJavaScript() &&3746Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) {3747Passes.emplace_back([&](const Environment &Env) {3748return JavaScriptRequoter(Env, Expanded).process(/*SkipAnnotation=*/true);3749});3750}37513752Passes.emplace_back([&](const Environment &Env) {3753return Formatter(Env, Expanded, Status).process();3754});37553756if (Style.isJavaScript() &&3757Style.InsertTrailingCommas == FormatStyle::TCS_Wrapped) {3758Passes.emplace_back([&](const Environment &Env) {3759return TrailingCommaInserter(Env, Expanded).process();3760});3761}37623763std::optional<std::string> CurrentCode;3764tooling::Replacements Fixes;3765unsigned Penalty = 0;3766for (size_t I = 0, E = Passes.size(); I < E; ++I) {3767std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env);3768auto NewCode = applyAllReplacements(3769CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first);3770if (NewCode) {3771Fixes = Fixes.merge(PassFixes.first);3772Penalty += PassFixes.second;3773if (I + 1 < E) {3774CurrentCode = std::move(*NewCode);3775Env = Environment::make(3776*CurrentCode, FileName,3777tooling::calculateRangesAfterReplacements(Fixes, Ranges),3778FirstStartColumn, NextStartColumn, LastStartColumn);3779if (!Env)3780return {};3781}3782}3783}37843785if (Style.QualifierAlignment != FormatStyle::QAS_Leave) {3786// Don't make replacements that replace nothing. QualifierAlignment can3787// produce them if one of its early passes changes e.g. `const volatile` to3788// `volatile const` and then a later pass changes it back again.3789tooling::Replacements NonNoOpFixes;3790for (const tooling::Replacement &Fix : Fixes) {3791StringRef OriginalCode = Code.substr(Fix.getOffset(), Fix.getLength());3792if (OriginalCode != Fix.getReplacementText()) {3793auto Err = NonNoOpFixes.add(Fix);3794if (Err) {3795llvm::errs() << "Error adding replacements : "3796<< toString(std::move(Err)) << "\n";3797}3798}3799}3800Fixes = std::move(NonNoOpFixes);3801}38023803return {Fixes, Penalty};3804}3805} // namespace internal38063807tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,3808ArrayRef<tooling::Range> Ranges,3809StringRef FileName,3810FormattingAttemptStatus *Status) {3811return internal::reformat(Style, Code, Ranges,3812/*FirstStartColumn=*/0,3813/*NextStartColumn=*/0,3814/*LastStartColumn=*/0, FileName, Status)3815.first;3816}38173818tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code,3819ArrayRef<tooling::Range> Ranges,3820StringRef FileName) {3821// cleanups only apply to C++ (they mostly concern ctor commas etc.)3822if (Style.Language != FormatStyle::LK_Cpp)3823return tooling::Replacements();3824auto Env = Environment::make(Code, FileName, Ranges);3825if (!Env)3826return {};3827return Cleaner(*Env, Style).process().first;3828}38293830tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,3831ArrayRef<tooling::Range> Ranges,3832StringRef FileName, bool *IncompleteFormat) {3833FormattingAttemptStatus Status;3834auto Result = reformat(Style, Code, Ranges, FileName, &Status);3835if (!Status.FormatComplete)3836*IncompleteFormat = true;3837return Result;3838}38393840tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style,3841StringRef Code,3842ArrayRef<tooling::Range> Ranges,3843StringRef FileName) {3844auto Env = Environment::make(Code, FileName, Ranges);3845if (!Env)3846return {};3847return NamespaceEndCommentsFixer(*Env, Style).process().first;3848}38493850tooling::Replacements sortUsingDeclarations(const FormatStyle &Style,3851StringRef Code,3852ArrayRef<tooling::Range> Ranges,3853StringRef FileName) {3854auto Env = Environment::make(Code, FileName, Ranges);3855if (!Env)3856return {};3857return UsingDeclarationsSorter(*Env, Style).process().first;3858}38593860LangOptions getFormattingLangOpts(const FormatStyle &Style) {3861LangOptions LangOpts;38623863FormatStyle::LanguageStandard LexingStd = Style.Standard;3864if (LexingStd == FormatStyle::LS_Auto)3865LexingStd = FormatStyle::LS_Latest;3866if (LexingStd == FormatStyle::LS_Latest)3867LexingStd = FormatStyle::LS_Cpp20;3868LangOpts.CPlusPlus = 1;3869LangOpts.CPlusPlus11 = LexingStd >= FormatStyle::LS_Cpp11;3870LangOpts.CPlusPlus14 = LexingStd >= FormatStyle::LS_Cpp14;3871LangOpts.CPlusPlus17 = LexingStd >= FormatStyle::LS_Cpp17;3872LangOpts.CPlusPlus20 = LexingStd >= FormatStyle::LS_Cpp20;3873LangOpts.Char8 = LexingStd >= FormatStyle::LS_Cpp20;3874// Turning on digraphs in standards before C++0x is error-prone, because e.g.3875// the sequence "<::" will be unconditionally treated as "[:".3876// Cf. Lexer::LexTokenInternal.3877LangOpts.Digraphs = LexingStd >= FormatStyle::LS_Cpp11;38783879LangOpts.LineComment = 1;3880LangOpts.CXXOperatorNames = Style.isCpp();3881LangOpts.Bool = 1;3882LangOpts.ObjC = 1;3883LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally.3884LangOpts.DeclSpecKeyword = 1; // To get __declspec.3885LangOpts.C99 = 1; // To get kw_restrict for non-underscore-prefixed restrict.3886return LangOpts;3887}38883889const char *StyleOptionHelpDescription =3890"Set coding style. <string> can be:\n"3891"1. A preset: LLVM, GNU, Google, Chromium, Microsoft,\n"3892" Mozilla, WebKit.\n"3893"2. 'file' to load style configuration from a\n"3894" .clang-format file in one of the parent directories\n"3895" of the source file (for stdin, see --assume-filename).\n"3896" If no .clang-format file is found, falls back to\n"3897" --fallback-style.\n"3898" --style=file is the default.\n"3899"3. 'file:<format_file_path>' to explicitly specify\n"3900" the configuration file.\n"3901"4. \"{key: value, ...}\" to set specific parameters, e.g.:\n"3902" --style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";39033904static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) {3905if (FileName.ends_with(".java"))3906return FormatStyle::LK_Java;3907if (FileName.ends_with_insensitive(".js") ||3908FileName.ends_with_insensitive(".mjs") ||3909FileName.ends_with_insensitive(".ts")) {3910return FormatStyle::LK_JavaScript; // (module) JavaScript or TypeScript.3911}3912if (FileName.ends_with(".m") || FileName.ends_with(".mm"))3913return FormatStyle::LK_ObjC;3914if (FileName.ends_with_insensitive(".proto") ||3915FileName.ends_with_insensitive(".protodevel")) {3916return FormatStyle::LK_Proto;3917}3918// txtpb is the canonical extension, and textproto is the legacy canonical3919// extension3920// https://protobuf.dev/reference/protobuf/textformat-spec/#text-format-files3921if (FileName.ends_with_insensitive(".txtpb") ||3922FileName.ends_with_insensitive(".textpb") ||3923FileName.ends_with_insensitive(".pb.txt") ||3924FileName.ends_with_insensitive(".textproto") ||3925FileName.ends_with_insensitive(".asciipb")) {3926return FormatStyle::LK_TextProto;3927}3928if (FileName.ends_with_insensitive(".td"))3929return FormatStyle::LK_TableGen;3930if (FileName.ends_with_insensitive(".cs"))3931return FormatStyle::LK_CSharp;3932if (FileName.ends_with_insensitive(".json"))3933return FormatStyle::LK_Json;3934if (FileName.ends_with_insensitive(".sv") ||3935FileName.ends_with_insensitive(".svh") ||3936FileName.ends_with_insensitive(".v") ||3937FileName.ends_with_insensitive(".vh")) {3938return FormatStyle::LK_Verilog;3939}3940return FormatStyle::LK_Cpp;3941}39423943FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) {3944const auto GuessedLanguage = getLanguageByFileName(FileName);3945if (GuessedLanguage == FormatStyle::LK_Cpp) {3946auto Extension = llvm::sys::path::extension(FileName);3947// If there's no file extension (or it's .h), we need to check the contents3948// of the code to see if it contains Objective-C.3949if (!Code.empty() && (Extension.empty() || Extension == ".h")) {3950auto NonEmptyFileName = FileName.empty() ? "guess.h" : FileName;3951Environment Env(Code, NonEmptyFileName, /*Ranges=*/{});3952ObjCHeaderStyleGuesser Guesser(Env, getLLVMStyle());3953Guesser.process();3954if (Guesser.isObjC())3955return FormatStyle::LK_ObjC;3956}3957}3958return GuessedLanguage;3959}39603961// Update StyleOptionHelpDescription above when changing this.3962const char *DefaultFormatStyle = "file";39633964const char *DefaultFallbackStyle = "LLVM";39653966llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>3967loadAndParseConfigFile(StringRef ConfigFile, llvm::vfs::FileSystem *FS,3968FormatStyle *Style, bool AllowUnknownOptions,3969llvm::SourceMgr::DiagHandlerTy DiagHandler) {3970llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =3971FS->getBufferForFile(ConfigFile.str());3972if (auto EC = Text.getError())3973return EC;3974if (auto EC = parseConfiguration(*Text.get(), Style, AllowUnknownOptions,3975DiagHandler)) {3976return EC;3977}3978return Text;3979}39803981Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,3982StringRef FallbackStyleName, StringRef Code,3983llvm::vfs::FileSystem *FS,3984bool AllowUnknownOptions,3985llvm::SourceMgr::DiagHandlerTy DiagHandler) {3986FormatStyle Style = getLLVMStyle(guessLanguage(FileName, Code));3987FormatStyle FallbackStyle = getNoStyle();3988if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle))3989return make_string_error("Invalid fallback style: " + FallbackStyleName);39903991SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 1> ChildFormatTextToApply;39923993if (StyleName.starts_with("{")) {3994// Parse YAML/JSON style from the command line.3995StringRef Source = "<command-line>";3996if (std::error_code ec =3997parseConfiguration(llvm::MemoryBufferRef(StyleName, Source), &Style,3998AllowUnknownOptions, DiagHandler)) {3999return make_string_error("Error parsing -style: " + ec.message());4000}40014002if (!Style.InheritsParentConfig)4003return Style;40044005ChildFormatTextToApply.emplace_back(4006llvm::MemoryBuffer::getMemBuffer(StyleName, Source, false));4007}40084009if (!FS)4010FS = llvm::vfs::getRealFileSystem().get();4011assert(FS);40124013// User provided clang-format file using -style=file:path/to/format/file.4014if (!Style.InheritsParentConfig &&4015StyleName.starts_with_insensitive("file:")) {4016auto ConfigFile = StyleName.substr(5);4017llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =4018loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions,4019DiagHandler);4020if (auto EC = Text.getError()) {4021return make_string_error("Error reading " + ConfigFile + ": " +4022EC.message());4023}40244025LLVM_DEBUG(llvm::dbgs()4026<< "Using configuration file " << ConfigFile << "\n");40274028if (!Style.InheritsParentConfig)4029return Style;40304031// Search for parent configs starting from the parent directory of4032// ConfigFile.4033FileName = ConfigFile;4034ChildFormatTextToApply.emplace_back(std::move(*Text));4035}40364037// If the style inherits the parent configuration it is a command line4038// configuration, which wants to inherit, so we have to skip the check of the4039// StyleName.4040if (!Style.InheritsParentConfig && !StyleName.equals_insensitive("file")) {4041if (!getPredefinedStyle(StyleName, Style.Language, &Style))4042return make_string_error("Invalid value for -style");4043if (!Style.InheritsParentConfig)4044return Style;4045}40464047SmallString<128> Path(FileName);4048if (std::error_code EC = FS->makeAbsolute(Path))4049return make_string_error(EC.message());40504051// Reset possible inheritance4052Style.InheritsParentConfig = false;40534054auto dropDiagnosticHandler = [](const llvm::SMDiagnostic &, void *) {};40554056auto applyChildFormatTexts = [&](FormatStyle *Style) {4057for (const auto &MemBuf : llvm::reverse(ChildFormatTextToApply)) {4058auto EC =4059parseConfiguration(*MemBuf, Style, AllowUnknownOptions,4060DiagHandler ? DiagHandler : dropDiagnosticHandler);4061// It was already correctly parsed.4062assert(!EC);4063static_cast<void>(EC);4064}4065};40664067// Look for .clang-format/_clang-format file in the file's parent directories.4068SmallVector<std::string, 2> FilesToLookFor;4069FilesToLookFor.push_back(".clang-format");4070FilesToLookFor.push_back("_clang-format");40714072SmallString<128> UnsuitableConfigFiles;4073for (StringRef Directory = Path; !Directory.empty();4074Directory = llvm::sys::path::parent_path(Directory)) {4075auto Status = FS->status(Directory);4076if (!Status ||4077Status->getType() != llvm::sys::fs::file_type::directory_file) {4078continue;4079}40804081for (const auto &F : FilesToLookFor) {4082SmallString<128> ConfigFile(Directory);40834084llvm::sys::path::append(ConfigFile, F);4085LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");40864087Status = FS->status(ConfigFile);4088if (!Status ||4089Status->getType() != llvm::sys::fs::file_type::regular_file) {4090continue;4091}40924093llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =4094loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions,4095DiagHandler);4096if (auto EC = Text.getError()) {4097if (EC != ParseError::Unsuitable) {4098return make_string_error("Error reading " + ConfigFile + ": " +4099EC.message());4100}4101if (!UnsuitableConfigFiles.empty())4102UnsuitableConfigFiles.append(", ");4103UnsuitableConfigFiles.append(ConfigFile);4104continue;4105}41064107LLVM_DEBUG(llvm::dbgs()4108<< "Using configuration file " << ConfigFile << "\n");41094110if (!Style.InheritsParentConfig) {4111if (!ChildFormatTextToApply.empty()) {4112LLVM_DEBUG(llvm::dbgs() << "Applying child configurations\n");4113applyChildFormatTexts(&Style);4114}4115return Style;4116}41174118LLVM_DEBUG(llvm::dbgs() << "Inherits parent configuration\n");41194120// Reset inheritance of style4121Style.InheritsParentConfig = false;41224123ChildFormatTextToApply.emplace_back(std::move(*Text));41244125// Breaking out of the inner loop, since we don't want to parse4126// .clang-format AND _clang-format, if both exist. Then we continue the4127// outer loop (parent directories) in search for the parent4128// configuration.4129break;4130}4131}41324133if (!UnsuitableConfigFiles.empty()) {4134return make_string_error("Configuration file(s) do(es) not support " +4135getLanguageName(Style.Language) + ": " +4136UnsuitableConfigFiles);4137}41384139if (!ChildFormatTextToApply.empty()) {4140LLVM_DEBUG(llvm::dbgs()4141<< "Applying child configurations on fallback style\n");4142applyChildFormatTexts(&FallbackStyle);4143}41444145return FallbackStyle;4146}41474148static bool isClangFormatOnOff(StringRef Comment, bool On) {4149if (Comment == (On ? "/* clang-format on */" : "/* clang-format off */"))4150return true;41514152static const char ClangFormatOn[] = "// clang-format on";4153static const char ClangFormatOff[] = "// clang-format off";4154const unsigned Size = (On ? sizeof ClangFormatOn : sizeof ClangFormatOff) - 1;41554156return Comment.starts_with(On ? ClangFormatOn : ClangFormatOff) &&4157(Comment.size() == Size || Comment[Size] == ':');4158}41594160bool isClangFormatOn(StringRef Comment) {4161return isClangFormatOnOff(Comment, /*On=*/true);4162}41634164bool isClangFormatOff(StringRef Comment) {4165return isClangFormatOnOff(Comment, /*On=*/false);4166}41674168} // namespace format4169} // namespace clang417041714172