diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Format/Format.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Format/Format.cpp | 2214 |
1 files changed, 1571 insertions, 643 deletions
diff --git a/contrib/llvm-project/clang/lib/Format/Format.cpp b/contrib/llvm-project/clang/lib/Format/Format.cpp index 2b860d2a25f7..10fe35c79a4f 100644 --- a/contrib/llvm-project/clang/lib/Format/Format.cpp +++ b/contrib/llvm-project/clang/lib/Format/Format.cpp @@ -16,9 +16,14 @@ #include "AffectedRangeManager.h" #include "BreakableToken.h" #include "ContinuationIndenter.h" +#include "DefinitionBlockSeparator.h" #include "FormatInternal.h" +#include "FormatToken.h" #include "FormatTokenLexer.h" +#include "IntegerLiteralSeparatorFixer.h" #include "NamespaceEndCommentsFixer.h" +#include "ObjCPropertyAttributeOrderFixer.h" +#include "QualifierAlignmentFixer.h" #include "SortJavaScriptImports.h" #include "TokenAnalyzer.h" #include "TokenAnnotator.h" @@ -32,6 +37,7 @@ #include "clang/Lex/Lexer.h" #include "clang/Tooling/Inclusions/HeaderIncludes.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Sequence.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Debug.h" @@ -42,6 +48,7 @@ #include <algorithm> #include <memory> #include <mutex> +#include <optional> #include <string> #include <unordered_map> @@ -53,103 +60,84 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(clang::format::FormatStyle::RawStringFormat) namespace llvm { namespace yaml { -template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> { - static void enumeration(IO &IO, FormatStyle::LanguageKind &Value) { - IO.enumCase(Value, "Cpp", FormatStyle::LK_Cpp); - IO.enumCase(Value, "Java", FormatStyle::LK_Java); - IO.enumCase(Value, "JavaScript", FormatStyle::LK_JavaScript); - IO.enumCase(Value, "ObjC", FormatStyle::LK_ObjC); - IO.enumCase(Value, "Proto", FormatStyle::LK_Proto); - IO.enumCase(Value, "TableGen", FormatStyle::LK_TableGen); - IO.enumCase(Value, "TextProto", FormatStyle::LK_TextProto); - IO.enumCase(Value, "CSharp", FormatStyle::LK_CSharp); - IO.enumCase(Value, "Json", FormatStyle::LK_Json); - } -}; - -template <> struct ScalarEnumerationTraits<FormatStyle::LanguageStandard> { - static void enumeration(IO &IO, FormatStyle::LanguageStandard &Value) { - IO.enumCase(Value, "c++03", FormatStyle::LS_Cpp03); - IO.enumCase(Value, "C++03", FormatStyle::LS_Cpp03); // Legacy alias - IO.enumCase(Value, "Cpp03", FormatStyle::LS_Cpp03); // Legacy alias - - IO.enumCase(Value, "c++11", FormatStyle::LS_Cpp11); - IO.enumCase(Value, "C++11", FormatStyle::LS_Cpp11); // Legacy alias - - IO.enumCase(Value, "c++14", FormatStyle::LS_Cpp14); - IO.enumCase(Value, "c++17", FormatStyle::LS_Cpp17); - IO.enumCase(Value, "c++20", FormatStyle::LS_Cpp20); - - IO.enumCase(Value, "Latest", FormatStyle::LS_Latest); - IO.enumCase(Value, "Cpp11", FormatStyle::LS_Latest); // Legacy alias - IO.enumCase(Value, "Auto", FormatStyle::LS_Auto); - } -}; - template <> -struct ScalarEnumerationTraits<FormatStyle::LambdaBodyIndentationKind> { - static void enumeration(IO &IO, - FormatStyle::LambdaBodyIndentationKind &Value) { - IO.enumCase(Value, "Signature", FormatStyle::LBI_Signature); - IO.enumCase(Value, "OuterScope", FormatStyle::LBI_OuterScope); +struct ScalarEnumerationTraits<FormatStyle::BreakBeforeNoexceptSpecifierStyle> { + static void + enumeration(IO &IO, FormatStyle::BreakBeforeNoexceptSpecifierStyle &Value) { + IO.enumCase(Value, "Never", FormatStyle::BBNSS_Never); + IO.enumCase(Value, "OnlyWithParen", FormatStyle::BBNSS_OnlyWithParen); + IO.enumCase(Value, "Always", FormatStyle::BBNSS_Always); } }; -template <> struct ScalarEnumerationTraits<FormatStyle::UseTabStyle> { - static void enumeration(IO &IO, FormatStyle::UseTabStyle &Value) { - IO.enumCase(Value, "Never", FormatStyle::UT_Never); - IO.enumCase(Value, "false", FormatStyle::UT_Never); - IO.enumCase(Value, "Always", FormatStyle::UT_Always); - IO.enumCase(Value, "true", FormatStyle::UT_Always); - IO.enumCase(Value, "ForIndentation", FormatStyle::UT_ForIndentation); - IO.enumCase(Value, "ForContinuationAndIndentation", - FormatStyle::UT_ForContinuationAndIndentation); - IO.enumCase(Value, "AlignWithSpaces", FormatStyle::UT_AlignWithSpaces); - } -}; +template <> struct MappingTraits<FormatStyle::AlignConsecutiveStyle> { + static void enumInput(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) { + IO.enumCase(Value, "None", + FormatStyle::AlignConsecutiveStyle( + {/*Enabled=*/false, /*AcrossEmptyLines=*/false, + /*AcrossComments=*/false, /*AlignCompound=*/false, + /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); + IO.enumCase(Value, "Consecutive", + FormatStyle::AlignConsecutiveStyle( + {/*Enabled=*/true, /*AcrossEmptyLines=*/false, + /*AcrossComments=*/false, /*AlignCompound=*/false, + /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); + IO.enumCase(Value, "AcrossEmptyLines", + FormatStyle::AlignConsecutiveStyle( + {/*Enabled=*/true, /*AcrossEmptyLines=*/true, + /*AcrossComments=*/false, /*AlignCompound=*/false, + /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); + IO.enumCase(Value, "AcrossComments", + FormatStyle::AlignConsecutiveStyle( + {/*Enabled=*/true, /*AcrossEmptyLines=*/false, + /*AcrossComments=*/true, /*AlignCompound=*/false, + /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); + IO.enumCase(Value, "AcrossEmptyLinesAndComments", + FormatStyle::AlignConsecutiveStyle( + {/*Enabled=*/true, /*AcrossEmptyLines=*/true, + /*AcrossComments=*/true, /*AlignCompound=*/false, + /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); -template <> struct ScalarEnumerationTraits<FormatStyle::JavaScriptQuoteStyle> { - static void enumeration(IO &IO, FormatStyle::JavaScriptQuoteStyle &Value) { - IO.enumCase(Value, "Leave", FormatStyle::JSQS_Leave); - IO.enumCase(Value, "Single", FormatStyle::JSQS_Single); - IO.enumCase(Value, "Double", FormatStyle::JSQS_Double); + // For backward compatibility. + IO.enumCase(Value, "true", + FormatStyle::AlignConsecutiveStyle( + {/*Enabled=*/true, /*AcrossEmptyLines=*/false, + /*AcrossComments=*/false, /*AlignCompound=*/false, + /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); + IO.enumCase(Value, "false", + FormatStyle::AlignConsecutiveStyle( + {/*Enabled=*/false, /*AcrossEmptyLines=*/false, + /*AcrossComments=*/false, /*AlignCompound=*/false, + /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); } -}; -template <> struct ScalarEnumerationTraits<FormatStyle::ShortBlockStyle> { - static void enumeration(IO &IO, FormatStyle::ShortBlockStyle &Value) { - IO.enumCase(Value, "Never", FormatStyle::SBS_Never); - IO.enumCase(Value, "false", FormatStyle::SBS_Never); - IO.enumCase(Value, "Always", FormatStyle::SBS_Always); - IO.enumCase(Value, "true", FormatStyle::SBS_Always); - IO.enumCase(Value, "Empty", FormatStyle::SBS_Empty); + static void mapping(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) { + IO.mapOptional("Enabled", Value.Enabled); + IO.mapOptional("AcrossEmptyLines", Value.AcrossEmptyLines); + IO.mapOptional("AcrossComments", Value.AcrossComments); + IO.mapOptional("AlignCompound", Value.AlignCompound); + IO.mapOptional("AlignFunctionPointers", Value.AlignFunctionPointers); + IO.mapOptional("PadOperators", Value.PadOperators); } }; -template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> { - static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) { - IO.enumCase(Value, "None", FormatStyle::SFS_None); - IO.enumCase(Value, "false", FormatStyle::SFS_None); - IO.enumCase(Value, "All", FormatStyle::SFS_All); - IO.enumCase(Value, "true", FormatStyle::SFS_All); - IO.enumCase(Value, "Inline", FormatStyle::SFS_Inline); - IO.enumCase(Value, "InlineOnly", FormatStyle::SFS_InlineOnly); - IO.enumCase(Value, "Empty", FormatStyle::SFS_Empty); +template <> +struct MappingTraits<FormatStyle::ShortCaseStatementsAlignmentStyle> { + static void mapping(IO &IO, + FormatStyle::ShortCaseStatementsAlignmentStyle &Value) { + IO.mapOptional("Enabled", Value.Enabled); + IO.mapOptional("AcrossEmptyLines", Value.AcrossEmptyLines); + IO.mapOptional("AcrossComments", Value.AcrossComments); + IO.mapOptional("AlignCaseColons", Value.AlignCaseColons); } }; -template <> struct ScalarEnumerationTraits<FormatStyle::AlignConsecutiveStyle> { - static void enumeration(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) { - IO.enumCase(Value, "None", FormatStyle::ACS_None); - IO.enumCase(Value, "Consecutive", FormatStyle::ACS_Consecutive); - IO.enumCase(Value, "AcrossEmptyLines", FormatStyle::ACS_AcrossEmptyLines); - IO.enumCase(Value, "AcrossComments", FormatStyle::ACS_AcrossComments); - IO.enumCase(Value, "AcrossEmptyLinesAndComments", - FormatStyle::ACS_AcrossEmptyLinesAndComments); - - // For backward compability. - IO.enumCase(Value, "true", FormatStyle::ACS_Consecutive); - IO.enumCase(Value, "false", FormatStyle::ACS_None); +template <> +struct ScalarEnumerationTraits<FormatStyle::AttributeBreakingStyle> { + static void enumeration(IO &IO, FormatStyle::AttributeBreakingStyle &Value) { + IO.enumCase(Value, "Always", FormatStyle::ABS_Always); + IO.enumCase(Value, "Leave", FormatStyle::ABS_Leave); + IO.enumCase(Value, "Never", FormatStyle::ABS_Never); } }; @@ -163,28 +151,13 @@ struct ScalarEnumerationTraits<FormatStyle::ArrayInitializerAlignmentStyle> { } }; -template <> struct ScalarEnumerationTraits<FormatStyle::ShortIfStyle> { - static void enumeration(IO &IO, FormatStyle::ShortIfStyle &Value) { - IO.enumCase(Value, "Never", FormatStyle::SIS_Never); - IO.enumCase(Value, "WithoutElse", FormatStyle::SIS_WithoutElse); - IO.enumCase(Value, "OnlyFirstIf", FormatStyle::SIS_OnlyFirstIf); - IO.enumCase(Value, "AllIfsAndElse", FormatStyle::SIS_AllIfsAndElse); - - // For backward compatibility. - IO.enumCase(Value, "Always", FormatStyle::SIS_OnlyFirstIf); - IO.enumCase(Value, "false", FormatStyle::SIS_Never); - IO.enumCase(Value, "true", FormatStyle::SIS_WithoutElse); - } -}; - -template <> struct ScalarEnumerationTraits<FormatStyle::ShortLambdaStyle> { - static void enumeration(IO &IO, FormatStyle::ShortLambdaStyle &Value) { - IO.enumCase(Value, "None", FormatStyle::SLS_None); - IO.enumCase(Value, "false", FormatStyle::SLS_None); - IO.enumCase(Value, "Empty", FormatStyle::SLS_Empty); - IO.enumCase(Value, "Inline", FormatStyle::SLS_Inline); - IO.enumCase(Value, "All", FormatStyle::SLS_All); - IO.enumCase(Value, "true", FormatStyle::SLS_All); +template <> struct ScalarEnumerationTraits<FormatStyle::BinaryOperatorStyle> { + static void enumeration(IO &IO, FormatStyle::BinaryOperatorStyle &Value) { + IO.enumCase(Value, "All", FormatStyle::BOS_All); + IO.enumCase(Value, "true", FormatStyle::BOS_All); + IO.enumCase(Value, "None", FormatStyle::BOS_None); + IO.enumCase(Value, "false", FormatStyle::BOS_None); + IO.enumCase(Value, "NonAssignment", FormatStyle::BOS_NonAssignment); } }; @@ -196,20 +169,14 @@ template <> struct ScalarEnumerationTraits<FormatStyle::BinPackStyle> { } }; -template <> struct ScalarEnumerationTraits<FormatStyle::TrailingCommaStyle> { - static void enumeration(IO &IO, FormatStyle::TrailingCommaStyle &Value) { - IO.enumCase(Value, "None", FormatStyle::TCS_None); - IO.enumCase(Value, "Wrapped", FormatStyle::TCS_Wrapped); - } -}; - -template <> struct ScalarEnumerationTraits<FormatStyle::BinaryOperatorStyle> { - static void enumeration(IO &IO, FormatStyle::BinaryOperatorStyle &Value) { - IO.enumCase(Value, "All", FormatStyle::BOS_All); - IO.enumCase(Value, "true", FormatStyle::BOS_All); - IO.enumCase(Value, "None", FormatStyle::BOS_None); - IO.enumCase(Value, "false", FormatStyle::BOS_None); - IO.enumCase(Value, "NonAssignment", FormatStyle::BOS_NonAssignment); +template <> +struct ScalarEnumerationTraits<FormatStyle::BitFieldColonSpacingStyle> { + static void enumeration(IO &IO, + FormatStyle::BitFieldColonSpacingStyle &Value) { + IO.enumCase(Value, "Both", FormatStyle::BFCS_Both); + IO.enumCase(Value, "None", FormatStyle::BFCS_None); + IO.enumCase(Value, "Before", FormatStyle::BFCS_Before); + IO.enumCase(Value, "After", FormatStyle::BFCS_After); } }; @@ -227,6 +194,42 @@ template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> { } }; +template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> { + static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping) { + IO.mapOptional("AfterCaseLabel", Wrapping.AfterCaseLabel); + IO.mapOptional("AfterClass", Wrapping.AfterClass); + IO.mapOptional("AfterControlStatement", Wrapping.AfterControlStatement); + IO.mapOptional("AfterEnum", Wrapping.AfterEnum); + IO.mapOptional("AfterExternBlock", Wrapping.AfterExternBlock); + IO.mapOptional("AfterFunction", Wrapping.AfterFunction); + IO.mapOptional("AfterNamespace", Wrapping.AfterNamespace); + IO.mapOptional("AfterObjCDeclaration", Wrapping.AfterObjCDeclaration); + IO.mapOptional("AfterStruct", Wrapping.AfterStruct); + IO.mapOptional("AfterUnion", Wrapping.AfterUnion); + IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch); + IO.mapOptional("BeforeElse", Wrapping.BeforeElse); + IO.mapOptional("BeforeLambdaBody", Wrapping.BeforeLambdaBody); + IO.mapOptional("BeforeWhile", Wrapping.BeforeWhile); + IO.mapOptional("IndentBraces", Wrapping.IndentBraces); + IO.mapOptional("SplitEmptyFunction", Wrapping.SplitEmptyFunction); + IO.mapOptional("SplitEmptyRecord", Wrapping.SplitEmptyRecord); + IO.mapOptional("SplitEmptyNamespace", Wrapping.SplitEmptyNamespace); + } +}; + +template <> struct ScalarEnumerationTraits<FormatStyle::BracketAlignmentStyle> { + static void enumeration(IO &IO, FormatStyle::BracketAlignmentStyle &Value) { + IO.enumCase(Value, "Align", FormatStyle::BAS_Align); + IO.enumCase(Value, "DontAlign", FormatStyle::BAS_DontAlign); + IO.enumCase(Value, "AlwaysBreak", FormatStyle::BAS_AlwaysBreak); + IO.enumCase(Value, "BlockIndent", FormatStyle::BAS_BlockIndent); + + // For backward compatibility. + IO.enumCase(Value, "true", FormatStyle::BAS_Align); + IO.enumCase(Value, "false", FormatStyle::BAS_DontAlign); + } +}; + template <> struct ScalarEnumerationTraits< FormatStyle::BraceWrappingAfterControlStatementStyle> { @@ -244,6 +247,31 @@ struct ScalarEnumerationTraits< }; template <> +struct ScalarEnumerationTraits< + FormatStyle::BreakBeforeConceptDeclarationsStyle> { + static void + enumeration(IO &IO, FormatStyle::BreakBeforeConceptDeclarationsStyle &Value) { + IO.enumCase(Value, "Never", FormatStyle::BBCDS_Never); + IO.enumCase(Value, "Allowed", FormatStyle::BBCDS_Allowed); + IO.enumCase(Value, "Always", FormatStyle::BBCDS_Always); + + // For backward compatibility. + IO.enumCase(Value, "true", FormatStyle::BBCDS_Always); + IO.enumCase(Value, "false", FormatStyle::BBCDS_Allowed); + } +}; + +template <> +struct ScalarEnumerationTraits<FormatStyle::BreakBeforeInlineASMColonStyle> { + static void enumeration(IO &IO, + FormatStyle::BreakBeforeInlineASMColonStyle &Value) { + IO.enumCase(Value, "Never", FormatStyle::BBIAS_Never); + IO.enumCase(Value, "OnlyMultiline", FormatStyle::BBIAS_OnlyMultiline); + IO.enumCase(Value, "Always", FormatStyle::BBIAS_Always); + } +}; + +template <> struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> { static void enumeration(IO &IO, FormatStyle::BreakConstructorInitializersStyle &Value) { @@ -265,6 +293,48 @@ struct ScalarEnumerationTraits<FormatStyle::BreakInheritanceListStyle> { }; template <> +struct ScalarEnumerationTraits<FormatStyle::BreakTemplateDeclarationsStyle> { + static void enumeration(IO &IO, + FormatStyle::BreakTemplateDeclarationsStyle &Value) { + IO.enumCase(Value, "No", FormatStyle::BTDS_No); + IO.enumCase(Value, "MultiLine", FormatStyle::BTDS_MultiLine); + IO.enumCase(Value, "Yes", FormatStyle::BTDS_Yes); + + // For backward compatibility. + IO.enumCase(Value, "false", FormatStyle::BTDS_MultiLine); + IO.enumCase(Value, "true", FormatStyle::BTDS_Yes); + } +}; + +template <> +struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> { + static void + enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) { + IO.enumCase(Value, "None", FormatStyle::DRTBS_None); + IO.enumCase(Value, "All", FormatStyle::DRTBS_All); + IO.enumCase(Value, "TopLevel", FormatStyle::DRTBS_TopLevel); + + // For backward compatibility. + IO.enumCase(Value, "false", FormatStyle::DRTBS_None); + IO.enumCase(Value, "true", FormatStyle::DRTBS_All); + } +}; + +template <> +struct ScalarEnumerationTraits<FormatStyle::EscapedNewlineAlignmentStyle> { + static void enumeration(IO &IO, + FormatStyle::EscapedNewlineAlignmentStyle &Value) { + IO.enumCase(Value, "DontAlign", FormatStyle::ENAS_DontAlign); + IO.enumCase(Value, "Left", FormatStyle::ENAS_Left); + IO.enumCase(Value, "Right", FormatStyle::ENAS_Right); + + // For backward compatibility. + IO.enumCase(Value, "true", FormatStyle::ENAS_Left); + IO.enumCase(Value, "false", FormatStyle::ENAS_Right); + } +}; + +template <> struct ScalarEnumerationTraits<FormatStyle::EmptyLineAfterAccessModifierStyle> { static void enumeration(IO &IO, FormatStyle::EmptyLineAfterAccessModifierStyle &Value) { @@ -287,15 +357,6 @@ struct ScalarEnumerationTraits< }; template <> -struct ScalarEnumerationTraits<FormatStyle::PPDirectiveIndentStyle> { - static void enumeration(IO &IO, FormatStyle::PPDirectiveIndentStyle &Value) { - IO.enumCase(Value, "None", FormatStyle::PPDIS_None); - IO.enumCase(Value, "AfterHash", FormatStyle::PPDIS_AfterHash); - IO.enumCase(Value, "BeforeHash", FormatStyle::PPDIS_BeforeHash); - } -}; - -template <> struct ScalarEnumerationTraits<FormatStyle::IndentExternBlockStyle> { static void enumeration(IO &IO, FormatStyle::IndentExternBlockStyle &Value) { IO.enumCase(Value, "AfterExternBlock", FormatStyle::IEBS_AfterExternBlock); @@ -306,79 +367,84 @@ struct ScalarEnumerationTraits<FormatStyle::IndentExternBlockStyle> { } }; -template <> -struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> { - static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) { - IO.enumCase(Value, "None", FormatStyle::RTBS_None); - IO.enumCase(Value, "All", FormatStyle::RTBS_All); - IO.enumCase(Value, "TopLevel", FormatStyle::RTBS_TopLevel); - IO.enumCase(Value, "TopLevelDefinitions", - FormatStyle::RTBS_TopLevelDefinitions); - IO.enumCase(Value, "AllDefinitions", FormatStyle::RTBS_AllDefinitions); +template <> struct MappingTraits<FormatStyle::IntegerLiteralSeparatorStyle> { + static void mapping(IO &IO, FormatStyle::IntegerLiteralSeparatorStyle &Base) { + IO.mapOptional("Binary", Base.Binary); + IO.mapOptional("BinaryMinDigits", Base.BinaryMinDigits); + IO.mapOptional("Decimal", Base.Decimal); + IO.mapOptional("DecimalMinDigits", Base.DecimalMinDigits); + IO.mapOptional("Hex", Base.Hex); + IO.mapOptional("HexMinDigits", Base.HexMinDigits); } }; -template <> -struct ScalarEnumerationTraits<FormatStyle::BreakTemplateDeclarationsStyle> { - static void enumeration(IO &IO, - FormatStyle::BreakTemplateDeclarationsStyle &Value) { - IO.enumCase(Value, "No", FormatStyle::BTDS_No); - IO.enumCase(Value, "MultiLine", FormatStyle::BTDS_MultiLine); - IO.enumCase(Value, "Yes", FormatStyle::BTDS_Yes); +template <> struct ScalarEnumerationTraits<FormatStyle::JavaScriptQuoteStyle> { + static void enumeration(IO &IO, FormatStyle::JavaScriptQuoteStyle &Value) { + IO.enumCase(Value, "Leave", FormatStyle::JSQS_Leave); + IO.enumCase(Value, "Single", FormatStyle::JSQS_Single); + IO.enumCase(Value, "Double", FormatStyle::JSQS_Double); + } +}; - // For backward compatibility. - IO.enumCase(Value, "false", FormatStyle::BTDS_MultiLine); - IO.enumCase(Value, "true", FormatStyle::BTDS_Yes); +template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> { + static void enumeration(IO &IO, FormatStyle::LanguageKind &Value) { + IO.enumCase(Value, "Cpp", FormatStyle::LK_Cpp); + IO.enumCase(Value, "Java", FormatStyle::LK_Java); + IO.enumCase(Value, "JavaScript", FormatStyle::LK_JavaScript); + IO.enumCase(Value, "ObjC", FormatStyle::LK_ObjC); + IO.enumCase(Value, "Proto", FormatStyle::LK_Proto); + IO.enumCase(Value, "TableGen", FormatStyle::LK_TableGen); + IO.enumCase(Value, "TextProto", FormatStyle::LK_TextProto); + IO.enumCase(Value, "CSharp", FormatStyle::LK_CSharp); + IO.enumCase(Value, "Json", FormatStyle::LK_Json); + IO.enumCase(Value, "Verilog", FormatStyle::LK_Verilog); } }; -template <> -struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> { - static void - enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) { - IO.enumCase(Value, "None", FormatStyle::DRTBS_None); - IO.enumCase(Value, "All", FormatStyle::DRTBS_All); - IO.enumCase(Value, "TopLevel", FormatStyle::DRTBS_TopLevel); +template <> struct ScalarEnumerationTraits<FormatStyle::LanguageStandard> { + static void enumeration(IO &IO, FormatStyle::LanguageStandard &Value) { + IO.enumCase(Value, "c++03", FormatStyle::LS_Cpp03); + IO.enumCase(Value, "C++03", FormatStyle::LS_Cpp03); // Legacy alias + IO.enumCase(Value, "Cpp03", FormatStyle::LS_Cpp03); // Legacy alias - // For backward compatibility. - IO.enumCase(Value, "false", FormatStyle::DRTBS_None); - IO.enumCase(Value, "true", FormatStyle::DRTBS_All); + IO.enumCase(Value, "c++11", FormatStyle::LS_Cpp11); + IO.enumCase(Value, "C++11", FormatStyle::LS_Cpp11); // Legacy alias + + IO.enumCase(Value, "c++14", FormatStyle::LS_Cpp14); + IO.enumCase(Value, "c++17", FormatStyle::LS_Cpp17); + IO.enumCase(Value, "c++20", FormatStyle::LS_Cpp20); + + IO.enumCase(Value, "Latest", FormatStyle::LS_Latest); + IO.enumCase(Value, "Cpp11", FormatStyle::LS_Latest); // Legacy alias + IO.enumCase(Value, "Auto", FormatStyle::LS_Auto); } }; template <> -struct ScalarEnumerationTraits<FormatStyle::NamespaceIndentationKind> { +struct ScalarEnumerationTraits<FormatStyle::LambdaBodyIndentationKind> { static void enumeration(IO &IO, - FormatStyle::NamespaceIndentationKind &Value) { - IO.enumCase(Value, "None", FormatStyle::NI_None); - IO.enumCase(Value, "Inner", FormatStyle::NI_Inner); - IO.enumCase(Value, "All", FormatStyle::NI_All); + FormatStyle::LambdaBodyIndentationKind &Value) { + IO.enumCase(Value, "Signature", FormatStyle::LBI_Signature); + IO.enumCase(Value, "OuterScope", FormatStyle::LBI_OuterScope); } }; -template <> struct ScalarEnumerationTraits<FormatStyle::BracketAlignmentStyle> { - static void enumeration(IO &IO, FormatStyle::BracketAlignmentStyle &Value) { - IO.enumCase(Value, "Align", FormatStyle::BAS_Align); - IO.enumCase(Value, "DontAlign", FormatStyle::BAS_DontAlign); - IO.enumCase(Value, "AlwaysBreak", FormatStyle::BAS_AlwaysBreak); - - // For backward compatibility. - IO.enumCase(Value, "true", FormatStyle::BAS_Align); - IO.enumCase(Value, "false", FormatStyle::BAS_DontAlign); +template <> struct ScalarEnumerationTraits<FormatStyle::LineEndingStyle> { + static void enumeration(IO &IO, FormatStyle::LineEndingStyle &Value) { + IO.enumCase(Value, "LF", FormatStyle::LE_LF); + IO.enumCase(Value, "CRLF", FormatStyle::LE_CRLF); + IO.enumCase(Value, "DeriveLF", FormatStyle::LE_DeriveLF); + IO.enumCase(Value, "DeriveCRLF", FormatStyle::LE_DeriveCRLF); } }; template <> -struct ScalarEnumerationTraits<FormatStyle::EscapedNewlineAlignmentStyle> { +struct ScalarEnumerationTraits<FormatStyle::NamespaceIndentationKind> { static void enumeration(IO &IO, - FormatStyle::EscapedNewlineAlignmentStyle &Value) { - IO.enumCase(Value, "DontAlign", FormatStyle::ENAS_DontAlign); - IO.enumCase(Value, "Left", FormatStyle::ENAS_Left); - IO.enumCase(Value, "Right", FormatStyle::ENAS_Right); - - // For backward compatibility. - IO.enumCase(Value, "true", FormatStyle::ENAS_Left); - IO.enumCase(Value, "false", FormatStyle::ENAS_Right); + FormatStyle::NamespaceIndentationKind &Value) { + IO.enumCase(Value, "None", FormatStyle::NI_None); + IO.enumCase(Value, "Inner", FormatStyle::NI_Inner); + IO.enumCase(Value, "All", FormatStyle::NI_All); } }; @@ -395,6 +461,18 @@ template <> struct ScalarEnumerationTraits<FormatStyle::OperandAlignmentStyle> { } }; +template <> +struct ScalarEnumerationTraits<FormatStyle::PackConstructorInitializersStyle> { + static void + enumeration(IO &IO, FormatStyle::PackConstructorInitializersStyle &Value) { + IO.enumCase(Value, "Never", FormatStyle::PCIS_Never); + IO.enumCase(Value, "BinPack", FormatStyle::PCIS_BinPack); + IO.enumCase(Value, "CurrentLine", FormatStyle::PCIS_CurrentLine); + IO.enumCase(Value, "NextLine", FormatStyle::PCIS_NextLine); + IO.enumCase(Value, "NextLineOnly", FormatStyle::PCIS_NextLineOnly); + } +}; + template <> struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> { static void enumeration(IO &IO, FormatStyle::PointerAlignmentStyle &Value) { IO.enumCase(Value, "Middle", FormatStyle::PAS_Middle); @@ -408,13 +486,31 @@ template <> struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> { }; template <> -struct ScalarEnumerationTraits<FormatStyle::SpaceAroundPointerQualifiersStyle> { - static void - enumeration(IO &IO, FormatStyle::SpaceAroundPointerQualifiersStyle &Value) { - IO.enumCase(Value, "Default", FormatStyle::SAPQ_Default); - IO.enumCase(Value, "Before", FormatStyle::SAPQ_Before); - IO.enumCase(Value, "After", FormatStyle::SAPQ_After); - IO.enumCase(Value, "Both", FormatStyle::SAPQ_Both); +struct ScalarEnumerationTraits<FormatStyle::PPDirectiveIndentStyle> { + static void enumeration(IO &IO, FormatStyle::PPDirectiveIndentStyle &Value) { + IO.enumCase(Value, "None", FormatStyle::PPDIS_None); + IO.enumCase(Value, "AfterHash", FormatStyle::PPDIS_AfterHash); + IO.enumCase(Value, "BeforeHash", FormatStyle::PPDIS_BeforeHash); + } +}; + +template <> +struct ScalarEnumerationTraits<FormatStyle::QualifierAlignmentStyle> { + static void enumeration(IO &IO, FormatStyle::QualifierAlignmentStyle &Value) { + IO.enumCase(Value, "Leave", FormatStyle::QAS_Leave); + IO.enumCase(Value, "Left", FormatStyle::QAS_Left); + IO.enumCase(Value, "Right", FormatStyle::QAS_Right); + IO.enumCase(Value, "Custom", FormatStyle::QAS_Custom); + } +}; + +template <> struct MappingTraits<FormatStyle::RawStringFormat> { + static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) { + IO.mapOptional("Language", Format.Language); + IO.mapOptional("Delimiters", Format.Delimiters); + IO.mapOptional("EnclosingFunctions", Format.EnclosingFunctions); + IO.mapOptional("CanonicalDelimiter", Format.CanonicalDelimiter); + IO.mapOptional("BasedOnStyle", Format.BasedOnStyle); } }; @@ -429,34 +525,100 @@ struct ScalarEnumerationTraits<FormatStyle::ReferenceAlignmentStyle> { }; template <> -struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensOptions> { +struct ScalarEnumerationTraits<FormatStyle::RemoveParenthesesStyle> { + static void enumeration(IO &IO, FormatStyle::RemoveParenthesesStyle &Value) { + IO.enumCase(Value, "Leave", FormatStyle::RPS_Leave); + IO.enumCase(Value, "MultipleParentheses", + FormatStyle::RPS_MultipleParentheses); + IO.enumCase(Value, "ReturnStatement", FormatStyle::RPS_ReturnStatement); + } +}; + +template <> +struct ScalarEnumerationTraits<FormatStyle::RequiresClausePositionStyle> { static void enumeration(IO &IO, - FormatStyle::SpaceBeforeParensOptions &Value) { - IO.enumCase(Value, "Never", FormatStyle::SBPO_Never); - IO.enumCase(Value, "ControlStatements", - FormatStyle::SBPO_ControlStatements); - IO.enumCase(Value, "ControlStatementsExceptControlMacros", - FormatStyle::SBPO_ControlStatementsExceptControlMacros); - IO.enumCase(Value, "NonEmptyParentheses", - FormatStyle::SBPO_NonEmptyParentheses); - IO.enumCase(Value, "Always", FormatStyle::SBPO_Always); + FormatStyle::RequiresClausePositionStyle &Value) { + IO.enumCase(Value, "OwnLine", FormatStyle::RCPS_OwnLine); + IO.enumCase(Value, "WithPreceding", FormatStyle::RCPS_WithPreceding); + IO.enumCase(Value, "WithFollowing", FormatStyle::RCPS_WithFollowing); + IO.enumCase(Value, "SingleLine", FormatStyle::RCPS_SingleLine); + } +}; - // For backward compatibility. - IO.enumCase(Value, "false", FormatStyle::SBPO_Never); - IO.enumCase(Value, "true", FormatStyle::SBPO_ControlStatements); - IO.enumCase(Value, "ControlStatementsExceptForEachMacros", - FormatStyle::SBPO_ControlStatementsExceptControlMacros); +template <> +struct ScalarEnumerationTraits<FormatStyle::RequiresExpressionIndentationKind> { + static void + enumeration(IO &IO, FormatStyle::RequiresExpressionIndentationKind &Value) { + IO.enumCase(Value, "Keyword", FormatStyle::REI_Keyword); + IO.enumCase(Value, "OuterScope", FormatStyle::REI_OuterScope); } }; template <> -struct ScalarEnumerationTraits<FormatStyle::BitFieldColonSpacingStyle> { - static void enumeration(IO &IO, - FormatStyle::BitFieldColonSpacingStyle &Value) { - IO.enumCase(Value, "Both", FormatStyle::BFCS_Both); - IO.enumCase(Value, "None", FormatStyle::BFCS_None); - IO.enumCase(Value, "Before", FormatStyle::BFCS_Before); - IO.enumCase(Value, "After", FormatStyle::BFCS_After); +struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> { + static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) { + IO.enumCase(Value, "None", FormatStyle::RTBS_None); + IO.enumCase(Value, "All", FormatStyle::RTBS_All); + IO.enumCase(Value, "TopLevel", FormatStyle::RTBS_TopLevel); + IO.enumCase(Value, "TopLevelDefinitions", + FormatStyle::RTBS_TopLevelDefinitions); + IO.enumCase(Value, "AllDefinitions", FormatStyle::RTBS_AllDefinitions); + } +}; + +template <> +struct ScalarEnumerationTraits<FormatStyle::SeparateDefinitionStyle> { + static void enumeration(IO &IO, FormatStyle::SeparateDefinitionStyle &Value) { + IO.enumCase(Value, "Leave", FormatStyle::SDS_Leave); + IO.enumCase(Value, "Always", FormatStyle::SDS_Always); + IO.enumCase(Value, "Never", FormatStyle::SDS_Never); + } +}; + +template <> struct ScalarEnumerationTraits<FormatStyle::ShortBlockStyle> { + static void enumeration(IO &IO, FormatStyle::ShortBlockStyle &Value) { + IO.enumCase(Value, "Never", FormatStyle::SBS_Never); + IO.enumCase(Value, "false", FormatStyle::SBS_Never); + IO.enumCase(Value, "Always", FormatStyle::SBS_Always); + IO.enumCase(Value, "true", FormatStyle::SBS_Always); + IO.enumCase(Value, "Empty", FormatStyle::SBS_Empty); + } +}; + +template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> { + static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) { + IO.enumCase(Value, "None", FormatStyle::SFS_None); + IO.enumCase(Value, "false", FormatStyle::SFS_None); + IO.enumCase(Value, "All", FormatStyle::SFS_All); + IO.enumCase(Value, "true", FormatStyle::SFS_All); + IO.enumCase(Value, "Inline", FormatStyle::SFS_Inline); + IO.enumCase(Value, "InlineOnly", FormatStyle::SFS_InlineOnly); + IO.enumCase(Value, "Empty", FormatStyle::SFS_Empty); + } +}; + +template <> struct ScalarEnumerationTraits<FormatStyle::ShortIfStyle> { + static void enumeration(IO &IO, FormatStyle::ShortIfStyle &Value) { + IO.enumCase(Value, "Never", FormatStyle::SIS_Never); + IO.enumCase(Value, "WithoutElse", FormatStyle::SIS_WithoutElse); + IO.enumCase(Value, "OnlyFirstIf", FormatStyle::SIS_OnlyFirstIf); + IO.enumCase(Value, "AllIfsAndElse", FormatStyle::SIS_AllIfsAndElse); + + // For backward compatibility. + IO.enumCase(Value, "Always", FormatStyle::SIS_OnlyFirstIf); + IO.enumCase(Value, "false", FormatStyle::SIS_Never); + IO.enumCase(Value, "true", FormatStyle::SIS_WithoutElse); + } +}; + +template <> struct ScalarEnumerationTraits<FormatStyle::ShortLambdaStyle> { + static void enumeration(IO &IO, FormatStyle::ShortLambdaStyle &Value) { + IO.enumCase(Value, "None", FormatStyle::SLS_None); + IO.enumCase(Value, "false", FormatStyle::SLS_None); + IO.enumCase(Value, "Empty", FormatStyle::SLS_Empty); + IO.enumCase(Value, "Inline", FormatStyle::SLS_Inline); + IO.enumCase(Value, "All", FormatStyle::SLS_All); + IO.enumCase(Value, "true", FormatStyle::SLS_All); } }; @@ -481,6 +643,72 @@ struct ScalarEnumerationTraits<FormatStyle::SortJavaStaticImportOptions> { } }; +template <> +struct ScalarEnumerationTraits<FormatStyle::SortUsingDeclarationsOptions> { + static void enumeration(IO &IO, + FormatStyle::SortUsingDeclarationsOptions &Value) { + IO.enumCase(Value, "Never", FormatStyle::SUD_Never); + IO.enumCase(Value, "Lexicographic", FormatStyle::SUD_Lexicographic); + IO.enumCase(Value, "LexicographicNumeric", + FormatStyle::SUD_LexicographicNumeric); + + // For backward compatibility. + IO.enumCase(Value, "false", FormatStyle::SUD_Never); + IO.enumCase(Value, "true", FormatStyle::SUD_LexicographicNumeric); + } +}; + +template <> +struct ScalarEnumerationTraits<FormatStyle::SpaceAroundPointerQualifiersStyle> { + static void + enumeration(IO &IO, FormatStyle::SpaceAroundPointerQualifiersStyle &Value) { + IO.enumCase(Value, "Default", FormatStyle::SAPQ_Default); + IO.enumCase(Value, "Before", FormatStyle::SAPQ_Before); + IO.enumCase(Value, "After", FormatStyle::SAPQ_After); + IO.enumCase(Value, "Both", FormatStyle::SAPQ_Both); + } +}; + +template <> struct MappingTraits<FormatStyle::SpaceBeforeParensCustom> { + static void mapping(IO &IO, FormatStyle::SpaceBeforeParensCustom &Spacing) { + IO.mapOptional("AfterControlStatements", Spacing.AfterControlStatements); + IO.mapOptional("AfterForeachMacros", Spacing.AfterForeachMacros); + IO.mapOptional("AfterFunctionDefinitionName", + Spacing.AfterFunctionDefinitionName); + IO.mapOptional("AfterFunctionDeclarationName", + Spacing.AfterFunctionDeclarationName); + IO.mapOptional("AfterIfMacros", Spacing.AfterIfMacros); + IO.mapOptional("AfterOverloadedOperator", Spacing.AfterOverloadedOperator); + IO.mapOptional("AfterPlacementOperator", Spacing.AfterPlacementOperator); + IO.mapOptional("AfterRequiresInClause", Spacing.AfterRequiresInClause); + IO.mapOptional("AfterRequiresInExpression", + Spacing.AfterRequiresInExpression); + IO.mapOptional("BeforeNonEmptyParentheses", + Spacing.BeforeNonEmptyParentheses); + } +}; + +template <> +struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensStyle> { + static void enumeration(IO &IO, FormatStyle::SpaceBeforeParensStyle &Value) { + IO.enumCase(Value, "Never", FormatStyle::SBPO_Never); + IO.enumCase(Value, "ControlStatements", + FormatStyle::SBPO_ControlStatements); + IO.enumCase(Value, "ControlStatementsExceptControlMacros", + FormatStyle::SBPO_ControlStatementsExceptControlMacros); + IO.enumCase(Value, "NonEmptyParentheses", + FormatStyle::SBPO_NonEmptyParentheses); + IO.enumCase(Value, "Always", FormatStyle::SBPO_Always); + IO.enumCase(Value, "Custom", FormatStyle::SBPO_Custom); + + // For backward compatibility. + IO.enumCase(Value, "false", FormatStyle::SBPO_Never); + IO.enumCase(Value, "true", FormatStyle::SBPO_ControlStatements); + IO.enumCase(Value, "ControlStatementsExceptForEachMacros", + FormatStyle::SBPO_ControlStatementsExceptControlMacros); + } +}; + template <> struct ScalarEnumerationTraits<FormatStyle::SpacesInAnglesStyle> { static void enumeration(IO &IO, FormatStyle::SpacesInAnglesStyle &Value) { IO.enumCase(Value, "Never", FormatStyle::SIAS_Never); @@ -493,26 +721,115 @@ template <> struct ScalarEnumerationTraits<FormatStyle::SpacesInAnglesStyle> { } }; +template <> struct MappingTraits<FormatStyle::SpacesInLineComment> { + static void mapping(IO &IO, FormatStyle::SpacesInLineComment &Space) { + // Transform the maximum to signed, to parse "-1" correctly + int signedMaximum = static_cast<int>(Space.Maximum); + IO.mapOptional("Minimum", Space.Minimum); + IO.mapOptional("Maximum", signedMaximum); + Space.Maximum = static_cast<unsigned>(signedMaximum); + + if (Space.Maximum != -1u) + Space.Minimum = std::min(Space.Minimum, Space.Maximum); + } +}; + +template <> struct MappingTraits<FormatStyle::SpacesInParensCustom> { + static void mapping(IO &IO, FormatStyle::SpacesInParensCustom &Spaces) { + IO.mapOptional("InCStyleCasts", Spaces.InCStyleCasts); + IO.mapOptional("InConditionalStatements", Spaces.InConditionalStatements); + IO.mapOptional("InEmptyParentheses", Spaces.InEmptyParentheses); + IO.mapOptional("Other", Spaces.Other); + } +}; + +template <> struct ScalarEnumerationTraits<FormatStyle::SpacesInParensStyle> { + static void enumeration(IO &IO, FormatStyle::SpacesInParensStyle &Value) { + IO.enumCase(Value, "Never", FormatStyle::SIPO_Never); + IO.enumCase(Value, "Custom", FormatStyle::SIPO_Custom); + } +}; + +template <> struct ScalarEnumerationTraits<FormatStyle::TrailingCommaStyle> { + static void enumeration(IO &IO, FormatStyle::TrailingCommaStyle &Value) { + IO.enumCase(Value, "None", FormatStyle::TCS_None); + IO.enumCase(Value, "Wrapped", FormatStyle::TCS_Wrapped); + } +}; + +template <> +struct ScalarEnumerationTraits<FormatStyle::TrailingCommentsAlignmentKinds> { + static void enumeration(IO &IO, + FormatStyle::TrailingCommentsAlignmentKinds &Value) { + IO.enumCase(Value, "Leave", FormatStyle::TCAS_Leave); + IO.enumCase(Value, "Always", FormatStyle::TCAS_Always); + IO.enumCase(Value, "Never", FormatStyle::TCAS_Never); + } +}; + +template <> struct MappingTraits<FormatStyle::TrailingCommentsAlignmentStyle> { + static void enumInput(IO &IO, + FormatStyle::TrailingCommentsAlignmentStyle &Value) { + IO.enumCase(Value, "Leave", + FormatStyle::TrailingCommentsAlignmentStyle( + {FormatStyle::TCAS_Leave, 0})); + + IO.enumCase(Value, "Always", + FormatStyle::TrailingCommentsAlignmentStyle( + {FormatStyle::TCAS_Always, 0})); + + IO.enumCase(Value, "Never", + FormatStyle::TrailingCommentsAlignmentStyle( + {FormatStyle::TCAS_Never, 0})); + + // For backwards compatibility + IO.enumCase(Value, "true", + FormatStyle::TrailingCommentsAlignmentStyle( + {FormatStyle::TCAS_Always, 0})); + IO.enumCase(Value, "false", + FormatStyle::TrailingCommentsAlignmentStyle( + {FormatStyle::TCAS_Never, 0})); + } + + static void mapping(IO &IO, + FormatStyle::TrailingCommentsAlignmentStyle &Value) { + IO.mapOptional("Kind", Value.Kind); + IO.mapOptional("OverEmptyLines", Value.OverEmptyLines); + } +}; + +template <> struct ScalarEnumerationTraits<FormatStyle::UseTabStyle> { + static void enumeration(IO &IO, FormatStyle::UseTabStyle &Value) { + IO.enumCase(Value, "Never", FormatStyle::UT_Never); + IO.enumCase(Value, "false", FormatStyle::UT_Never); + IO.enumCase(Value, "Always", FormatStyle::UT_Always); + IO.enumCase(Value, "true", FormatStyle::UT_Always); + IO.enumCase(Value, "ForIndentation", FormatStyle::UT_ForIndentation); + IO.enumCase(Value, "ForContinuationAndIndentation", + FormatStyle::UT_ForContinuationAndIndentation); + IO.enumCase(Value, "AlignWithSpaces", FormatStyle::UT_AlignWithSpaces); + } +}; + template <> struct MappingTraits<FormatStyle> { static void mapping(IO &IO, FormatStyle &Style) { // When reading, read the language first, we need it for getPredefinedStyle. IO.mapOptional("Language", Style.Language); + StringRef BasedOnStyle; if (IO.outputting()) { - StringRef StylesArray[] = {"LLVM", "Google", "Chromium", "Mozilla", - "WebKit", "GNU", "Microsoft"}; - ArrayRef<StringRef> Styles(StylesArray); - for (size_t i = 0, e = Styles.size(); i < e; ++i) { - StringRef StyleName(Styles[i]); + StringRef Styles[] = {"LLVM", "Google", "Chromium", "Mozilla", + "WebKit", "GNU", "Microsoft", "clang-format"}; + for (StringRef StyleName : Styles) { FormatStyle PredefinedStyle; if (getPredefinedStyle(StyleName, Style.Language, &PredefinedStyle) && Style == PredefinedStyle) { IO.mapOptional("# BasedOnStyle", StyleName); + BasedOnStyle = StyleName; break; } } } else { - StringRef BasedOnStyle; IO.mapOptional("BasedOnStyle", BasedOnStyle); if (!BasedOnStyle.empty()) { FormatStyle::LanguageKind OldLanguage = Style.Language; @@ -526,68 +843,101 @@ template <> struct MappingTraits<FormatStyle> { } } + // Initialize some variables used in the parsing. The using logic is at the + // end. + + // For backward compatibility: + // The default value of ConstructorInitializerAllOnOneLineOrOnePerLine was + // false unless BasedOnStyle was Google or Chromium whereas that of + // AllowAllConstructorInitializersOnNextLine was always true, so the + // equivalent default value of PackConstructorInitializers is PCIS_NextLine + // for Google/Chromium or PCIS_BinPack otherwise. If the deprecated options + // had a non-default value while PackConstructorInitializers has a default + // value, set the latter to an equivalent non-default value if needed. + const bool IsGoogleOrChromium = BasedOnStyle.equals_insensitive("google") || + BasedOnStyle.equals_insensitive("chromium"); + bool OnCurrentLine = IsGoogleOrChromium; + bool OnNextLine = true; + + bool BreakBeforeInheritanceComma = false; + bool BreakConstructorInitializersBeforeComma = false; + + bool DeriveLineEnding = true; + bool UseCRLF = false; + + bool SpaceInEmptyParentheses = false; + bool SpacesInConditionalStatement = false; + bool SpacesInCStyleCastParentheses = false; + bool SpacesInParentheses = false; + // For backward compatibility. if (!IO.outputting()) { IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlines); + IO.mapOptional("AllowAllConstructorInitializersOnNextLine", OnNextLine); + IO.mapOptional("BreakBeforeInheritanceComma", + BreakBeforeInheritanceComma); + IO.mapOptional("BreakConstructorInitializersBeforeComma", + BreakConstructorInitializersBeforeComma); + IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine", + OnCurrentLine); + IO.mapOptional("DeriveLineEnding", DeriveLineEnding); IO.mapOptional("DerivePointerBinding", Style.DerivePointerAlignment); IO.mapOptional("IndentFunctionDeclarationAfterType", Style.IndentWrappedFunctionNames); + IO.mapOptional("IndentRequires", Style.IndentRequiresClause); IO.mapOptional("PointerBindsToType", Style.PointerAlignment); IO.mapOptional("SpaceAfterControlStatementKeyword", Style.SpaceBeforeParens); + IO.mapOptional("SpaceInEmptyParentheses", SpaceInEmptyParentheses); + IO.mapOptional("SpacesInConditionalStatement", + SpacesInConditionalStatement); + IO.mapOptional("SpacesInCStyleCastParentheses", + SpacesInCStyleCastParentheses); + IO.mapOptional("SpacesInParentheses", SpacesInParentheses); + IO.mapOptional("UseCRLF", UseCRLF); } IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset); IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket); IO.mapOptional("AlignArrayOfStructures", Style.AlignArrayOfStructures); - IO.mapOptional("AlignConsecutiveMacros", Style.AlignConsecutiveMacros); IO.mapOptional("AlignConsecutiveAssignments", Style.AlignConsecutiveAssignments); IO.mapOptional("AlignConsecutiveBitFields", Style.AlignConsecutiveBitFields); IO.mapOptional("AlignConsecutiveDeclarations", Style.AlignConsecutiveDeclarations); + IO.mapOptional("AlignConsecutiveMacros", Style.AlignConsecutiveMacros); + IO.mapOptional("AlignConsecutiveShortCaseStatements", + Style.AlignConsecutiveShortCaseStatements); IO.mapOptional("AlignEscapedNewlines", Style.AlignEscapedNewlines); IO.mapOptional("AlignOperands", Style.AlignOperands); IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments); IO.mapOptional("AllowAllArgumentsOnNextLine", Style.AllowAllArgumentsOnNextLine); - IO.mapOptional("AllowAllConstructorInitializersOnNextLine", - Style.AllowAllConstructorInitializersOnNextLine); IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine", Style.AllowAllParametersOfDeclarationOnNextLine); - IO.mapOptional("AllowShortEnumsOnASingleLine", - Style.AllowShortEnumsOnASingleLine); + IO.mapOptional("AllowBreakBeforeNoexceptSpecifier", + Style.AllowBreakBeforeNoexceptSpecifier); IO.mapOptional("AllowShortBlocksOnASingleLine", Style.AllowShortBlocksOnASingleLine); IO.mapOptional("AllowShortCaseLabelsOnASingleLine", Style.AllowShortCaseLabelsOnASingleLine); + IO.mapOptional("AllowShortCompoundRequirementOnASingleLine", + Style.AllowShortCompoundRequirementOnASingleLine); + IO.mapOptional("AllowShortEnumsOnASingleLine", + Style.AllowShortEnumsOnASingleLine); IO.mapOptional("AllowShortFunctionsOnASingleLine", Style.AllowShortFunctionsOnASingleLine); - IO.mapOptional("AllowShortLambdasOnASingleLine", - Style.AllowShortLambdasOnASingleLine); IO.mapOptional("AllowShortIfStatementsOnASingleLine", Style.AllowShortIfStatementsOnASingleLine); + IO.mapOptional("AllowShortLambdasOnASingleLine", + Style.AllowShortLambdasOnASingleLine); IO.mapOptional("AllowShortLoopsOnASingleLine", Style.AllowShortLoopsOnASingleLine); IO.mapOptional("AlwaysBreakAfterDefinitionReturnType", Style.AlwaysBreakAfterDefinitionReturnType); IO.mapOptional("AlwaysBreakAfterReturnType", Style.AlwaysBreakAfterReturnType); - - // If AlwaysBreakAfterDefinitionReturnType was specified but - // AlwaysBreakAfterReturnType was not, initialize the latter from the - // former for backwards compatibility. - if (Style.AlwaysBreakAfterDefinitionReturnType != FormatStyle::DRTBS_None && - Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_None) { - if (Style.AlwaysBreakAfterDefinitionReturnType == FormatStyle::DRTBS_All) - Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions; - else if (Style.AlwaysBreakAfterDefinitionReturnType == - FormatStyle::DRTBS_TopLevel) - Style.AlwaysBreakAfterReturnType = - FormatStyle::RTBS_TopLevelDefinitions; - } - IO.mapOptional("AlwaysBreakBeforeMultilineStrings", Style.AlwaysBreakBeforeMultilineStrings); IO.mapOptional("AlwaysBreakTemplateDeclarations", @@ -595,51 +945,36 @@ template <> struct MappingTraits<FormatStyle> { IO.mapOptional("AttributeMacros", Style.AttributeMacros); IO.mapOptional("BinPackArguments", Style.BinPackArguments); IO.mapOptional("BinPackParameters", Style.BinPackParameters); + IO.mapOptional("BitFieldColonSpacing", Style.BitFieldColonSpacing); + IO.mapOptional("BracedInitializerIndentWidth", + Style.BracedInitializerIndentWidth); IO.mapOptional("BraceWrapping", Style.BraceWrapping); + IO.mapOptional("BreakAdjacentStringLiterals", + Style.BreakAdjacentStringLiterals); + IO.mapOptional("BreakAfterAttributes", Style.BreakAfterAttributes); + IO.mapOptional("BreakAfterJavaFieldAnnotations", + Style.BreakAfterJavaFieldAnnotations); + IO.mapOptional("BreakArrays", Style.BreakArrays); IO.mapOptional("BreakBeforeBinaryOperators", Style.BreakBeforeBinaryOperators); IO.mapOptional("BreakBeforeConceptDeclarations", Style.BreakBeforeConceptDeclarations); IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces); - - bool BreakBeforeInheritanceComma = false; - IO.mapOptional("BreakBeforeInheritanceComma", BreakBeforeInheritanceComma); - IO.mapOptional("BreakInheritanceList", Style.BreakInheritanceList); - // If BreakBeforeInheritanceComma was specified but - // BreakInheritance was not, initialize the latter from the - // former for backwards compatibility. - if (BreakBeforeInheritanceComma && - Style.BreakInheritanceList == FormatStyle::BILS_BeforeColon) - Style.BreakInheritanceList = FormatStyle::BILS_BeforeComma; - + IO.mapOptional("BreakBeforeInlineASMColon", + Style.BreakBeforeInlineASMColon); IO.mapOptional("BreakBeforeTernaryOperators", Style.BreakBeforeTernaryOperators); - - bool BreakConstructorInitializersBeforeComma = false; - IO.mapOptional("BreakConstructorInitializersBeforeComma", - BreakConstructorInitializersBeforeComma); IO.mapOptional("BreakConstructorInitializers", Style.BreakConstructorInitializers); - // If BreakConstructorInitializersBeforeComma was specified but - // BreakConstructorInitializers was not, initialize the latter from the - // former for backwards compatibility. - if (BreakConstructorInitializersBeforeComma && - Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon) - Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma; - - IO.mapOptional("BreakAfterJavaFieldAnnotations", - Style.BreakAfterJavaFieldAnnotations); + IO.mapOptional("BreakInheritanceList", Style.BreakInheritanceList); IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals); IO.mapOptional("ColumnLimit", Style.ColumnLimit); IO.mapOptional("CommentPragmas", Style.CommentPragmas); IO.mapOptional("CompactNamespaces", Style.CompactNamespaces); - IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine", - Style.ConstructorInitializerAllOnOneLineOrOnePerLine); IO.mapOptional("ConstructorInitializerIndentWidth", Style.ConstructorInitializerIndentWidth); IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth); IO.mapOptional("Cpp11BracedListStyle", Style.Cpp11BracedListStyle); - IO.mapOptional("DeriveLineEnding", Style.DeriveLineEnding); IO.mapOptional("DerivePointerAlignment", Style.DerivePointerAlignment); IO.mapOptional("DisableFormat", Style.DisableFormat); IO.mapOptional("EmptyLineAfterAccessModifier", @@ -651,31 +986,36 @@ template <> struct MappingTraits<FormatStyle> { IO.mapOptional("FixNamespaceComments", Style.FixNamespaceComments); IO.mapOptional("ForEachMacros", Style.ForEachMacros); IO.mapOptional("IfMacros", Style.IfMacros); - IO.mapOptional("IncludeBlocks", Style.IncludeStyle.IncludeBlocks); IO.mapOptional("IncludeCategories", Style.IncludeStyle.IncludeCategories); IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex); IO.mapOptional("IncludeIsMainSourceRegex", Style.IncludeStyle.IncludeIsMainSourceRegex); IO.mapOptional("IndentAccessModifiers", Style.IndentAccessModifiers); - IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels); IO.mapOptional("IndentCaseBlocks", Style.IndentCaseBlocks); + IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels); + IO.mapOptional("IndentExternBlock", Style.IndentExternBlock); IO.mapOptional("IndentGotoLabels", Style.IndentGotoLabels); IO.mapOptional("IndentPPDirectives", Style.IndentPPDirectives); - IO.mapOptional("IndentExternBlock", Style.IndentExternBlock); - IO.mapOptional("IndentRequires", Style.IndentRequires); + IO.mapOptional("IndentRequiresClause", Style.IndentRequiresClause); IO.mapOptional("IndentWidth", Style.IndentWidth); IO.mapOptional("IndentWrappedFunctionNames", Style.IndentWrappedFunctionNames); + IO.mapOptional("InsertBraces", Style.InsertBraces); + IO.mapOptional("InsertNewlineAtEOF", Style.InsertNewlineAtEOF); IO.mapOptional("InsertTrailingCommas", Style.InsertTrailingCommas); + IO.mapOptional("IntegerLiteralSeparator", Style.IntegerLiteralSeparator); IO.mapOptional("JavaImportGroups", Style.JavaImportGroups); IO.mapOptional("JavaScriptQuotes", Style.JavaScriptQuotes); IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports); IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks", Style.KeepEmptyLinesAtTheStartOfBlocks); + IO.mapOptional("KeepEmptyLinesAtEOF", Style.KeepEmptyLinesAtEOF); IO.mapOptional("LambdaBodyIndentation", Style.LambdaBodyIndentation); + IO.mapOptional("LineEnding", Style.LineEnding); IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin); IO.mapOptional("MacroBlockEnd", Style.MacroBlockEnd); + IO.mapOptional("Macros", Style.Macros); IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep); IO.mapOptional("NamespaceIndentation", Style.NamespaceIndentation); IO.mapOptional("NamespaceMacros", Style.NamespaceMacros); @@ -683,29 +1023,53 @@ template <> struct MappingTraits<FormatStyle> { IO.mapOptional("ObjCBlockIndentWidth", Style.ObjCBlockIndentWidth); IO.mapOptional("ObjCBreakBeforeNestedBlockParam", Style.ObjCBreakBeforeNestedBlockParam); + IO.mapOptional("ObjCPropertyAttributeOrder", + Style.ObjCPropertyAttributeOrder); IO.mapOptional("ObjCSpaceAfterProperty", Style.ObjCSpaceAfterProperty); IO.mapOptional("ObjCSpaceBeforeProtocolList", Style.ObjCSpaceBeforeProtocolList); + IO.mapOptional("PackConstructorInitializers", + Style.PackConstructorInitializers); IO.mapOptional("PenaltyBreakAssignment", Style.PenaltyBreakAssignment); IO.mapOptional("PenaltyBreakBeforeFirstCallParameter", Style.PenaltyBreakBeforeFirstCallParameter); IO.mapOptional("PenaltyBreakComment", Style.PenaltyBreakComment); IO.mapOptional("PenaltyBreakFirstLessLess", Style.PenaltyBreakFirstLessLess); + IO.mapOptional("PenaltyBreakOpenParenthesis", + Style.PenaltyBreakOpenParenthesis); + IO.mapOptional("PenaltyBreakScopeResolution", + Style.PenaltyBreakScopeResolution); IO.mapOptional("PenaltyBreakString", Style.PenaltyBreakString); IO.mapOptional("PenaltyBreakTemplateDeclaration", Style.PenaltyBreakTemplateDeclaration); IO.mapOptional("PenaltyExcessCharacter", Style.PenaltyExcessCharacter); - IO.mapOptional("PenaltyReturnTypeOnItsOwnLine", - Style.PenaltyReturnTypeOnItsOwnLine); IO.mapOptional("PenaltyIndentedWhitespace", Style.PenaltyIndentedWhitespace); + IO.mapOptional("PenaltyReturnTypeOnItsOwnLine", + Style.PenaltyReturnTypeOnItsOwnLine); IO.mapOptional("PointerAlignment", Style.PointerAlignment); IO.mapOptional("PPIndentWidth", Style.PPIndentWidth); + IO.mapOptional("QualifierAlignment", Style.QualifierAlignment); + // Default Order for Left/Right based Qualifier alignment. + if (Style.QualifierAlignment == FormatStyle::QAS_Right) + Style.QualifierOrder = {"type", "const", "volatile"}; + else if (Style.QualifierAlignment == FormatStyle::QAS_Left) + Style.QualifierOrder = {"const", "volatile", "type"}; + else if (Style.QualifierAlignment == FormatStyle::QAS_Custom) + IO.mapOptional("QualifierOrder", Style.QualifierOrder); IO.mapOptional("RawStringFormats", Style.RawStringFormats); IO.mapOptional("ReferenceAlignment", Style.ReferenceAlignment); IO.mapOptional("ReflowComments", Style.ReflowComments); + IO.mapOptional("RemoveBracesLLVM", Style.RemoveBracesLLVM); + IO.mapOptional("RemoveParentheses", Style.RemoveParentheses); + IO.mapOptional("RemoveSemicolon", Style.RemoveSemicolon); + IO.mapOptional("RequiresClausePosition", Style.RequiresClausePosition); + IO.mapOptional("RequiresExpressionIndentation", + Style.RequiresExpressionIndentation); + IO.mapOptional("SeparateDefinitionBlocks", Style.SeparateDefinitionBlocks); IO.mapOptional("ShortNamespaceLines", Style.ShortNamespaceLines); + IO.mapOptional("SkipMacroDefinitionBody", Style.SkipMacroDefinitionBody); IO.mapOptional("SortIncludes", Style.SortIncludes); IO.mapOptional("SortJavaStaticImport", Style.SortJavaStaticImport); IO.mapOptional("SortUsingDeclarations", Style.SortUsingDeclarations); @@ -713,6 +1077,8 @@ template <> struct MappingTraits<FormatStyle> { IO.mapOptional("SpaceAfterLogicalNot", Style.SpaceAfterLogicalNot); IO.mapOptional("SpaceAfterTemplateKeyword", Style.SpaceAfterTemplateKeyword); + IO.mapOptional("SpaceAroundPointerQualifiers", + Style.SpaceAroundPointerQualifiers); IO.mapOptional("SpaceBeforeAssignmentOperators", Style.SpaceBeforeAssignmentOperators); IO.mapOptional("SpaceBeforeCaseColon", Style.SpaceBeforeCaseColon); @@ -722,85 +1088,111 @@ template <> struct MappingTraits<FormatStyle> { Style.SpaceBeforeCtorInitializerColon); IO.mapOptional("SpaceBeforeInheritanceColon", Style.SpaceBeforeInheritanceColon); + IO.mapOptional("SpaceBeforeJsonColon", Style.SpaceBeforeJsonColon); IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens); - IO.mapOptional("SpaceAroundPointerQualifiers", - Style.SpaceAroundPointerQualifiers); + IO.mapOptional("SpaceBeforeParensOptions", Style.SpaceBeforeParensOptions); IO.mapOptional("SpaceBeforeRangeBasedForLoopColon", Style.SpaceBeforeRangeBasedForLoopColon); + IO.mapOptional("SpaceBeforeSquareBrackets", + Style.SpaceBeforeSquareBrackets); IO.mapOptional("SpaceInEmptyBlock", Style.SpaceInEmptyBlock); - IO.mapOptional("SpaceInEmptyParentheses", Style.SpaceInEmptyParentheses); IO.mapOptional("SpacesBeforeTrailingComments", Style.SpacesBeforeTrailingComments); IO.mapOptional("SpacesInAngles", Style.SpacesInAngles); - IO.mapOptional("SpacesInConditionalStatement", - Style.SpacesInConditionalStatement); IO.mapOptional("SpacesInContainerLiterals", Style.SpacesInContainerLiterals); - IO.mapOptional("SpacesInCStyleCastParentheses", - Style.SpacesInCStyleCastParentheses); IO.mapOptional("SpacesInLineCommentPrefix", Style.SpacesInLineCommentPrefix); - IO.mapOptional("SpacesInParentheses", Style.SpacesInParentheses); + IO.mapOptional("SpacesInParens", Style.SpacesInParens); + IO.mapOptional("SpacesInParensOptions", Style.SpacesInParensOptions); IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets); - IO.mapOptional("SpaceBeforeSquareBrackets", - Style.SpaceBeforeSquareBrackets); - IO.mapOptional("BitFieldColonSpacing", Style.BitFieldColonSpacing); IO.mapOptional("Standard", Style.Standard); IO.mapOptional("StatementAttributeLikeMacros", Style.StatementAttributeLikeMacros); IO.mapOptional("StatementMacros", Style.StatementMacros); IO.mapOptional("TabWidth", Style.TabWidth); + IO.mapOptional("TypeNames", Style.TypeNames); IO.mapOptional("TypenameMacros", Style.TypenameMacros); - IO.mapOptional("UseCRLF", Style.UseCRLF); IO.mapOptional("UseTab", Style.UseTab); + IO.mapOptional("VerilogBreakBetweenInstancePorts", + Style.VerilogBreakBetweenInstancePorts); IO.mapOptional("WhitespaceSensitiveMacros", Style.WhitespaceSensitiveMacros); - } -}; -template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> { - static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping) { - IO.mapOptional("AfterCaseLabel", Wrapping.AfterCaseLabel); - IO.mapOptional("AfterClass", Wrapping.AfterClass); - IO.mapOptional("AfterControlStatement", Wrapping.AfterControlStatement); - IO.mapOptional("AfterEnum", Wrapping.AfterEnum); - IO.mapOptional("AfterFunction", Wrapping.AfterFunction); - IO.mapOptional("AfterNamespace", Wrapping.AfterNamespace); - IO.mapOptional("AfterObjCDeclaration", Wrapping.AfterObjCDeclaration); - IO.mapOptional("AfterStruct", Wrapping.AfterStruct); - IO.mapOptional("AfterUnion", Wrapping.AfterUnion); - IO.mapOptional("AfterExternBlock", Wrapping.AfterExternBlock); - IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch); - IO.mapOptional("BeforeElse", Wrapping.BeforeElse); - IO.mapOptional("BeforeLambdaBody", Wrapping.BeforeLambdaBody); - IO.mapOptional("BeforeWhile", Wrapping.BeforeWhile); - IO.mapOptional("IndentBraces", Wrapping.IndentBraces); - IO.mapOptional("SplitEmptyFunction", Wrapping.SplitEmptyFunction); - IO.mapOptional("SplitEmptyRecord", Wrapping.SplitEmptyRecord); - IO.mapOptional("SplitEmptyNamespace", Wrapping.SplitEmptyNamespace); - } -}; + // If AlwaysBreakAfterDefinitionReturnType was specified but + // AlwaysBreakAfterReturnType was not, initialize the latter from the + // former for backwards compatibility. + if (Style.AlwaysBreakAfterDefinitionReturnType != FormatStyle::DRTBS_None && + Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_None) { + if (Style.AlwaysBreakAfterDefinitionReturnType == + FormatStyle::DRTBS_All) { + Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions; + } else if (Style.AlwaysBreakAfterDefinitionReturnType == + FormatStyle::DRTBS_TopLevel) { + Style.AlwaysBreakAfterReturnType = + FormatStyle::RTBS_TopLevelDefinitions; + } + } -template <> struct MappingTraits<FormatStyle::RawStringFormat> { - static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) { - IO.mapOptional("Language", Format.Language); - IO.mapOptional("Delimiters", Format.Delimiters); - IO.mapOptional("EnclosingFunctions", Format.EnclosingFunctions); - IO.mapOptional("CanonicalDelimiter", Format.CanonicalDelimiter); - IO.mapOptional("BasedOnStyle", Format.BasedOnStyle); - } -}; + // If BreakBeforeInheritanceComma was specified but BreakInheritance was + // not, initialize the latter from the former for backwards compatibility. + if (BreakBeforeInheritanceComma && + Style.BreakInheritanceList == FormatStyle::BILS_BeforeColon) { + Style.BreakInheritanceList = FormatStyle::BILS_BeforeComma; + } -template <> struct MappingTraits<FormatStyle::SpacesInLineComment> { - static void mapping(IO &IO, FormatStyle::SpacesInLineComment &Space) { - // Transform the maximum to signed, to parse "-1" correctly - int signedMaximum = static_cast<int>(Space.Maximum); - IO.mapOptional("Minimum", Space.Minimum); - IO.mapOptional("Maximum", signedMaximum); - Space.Maximum = static_cast<unsigned>(signedMaximum); + // If BreakConstructorInitializersBeforeComma was specified but + // BreakConstructorInitializers was not, initialize the latter from the + // former for backwards compatibility. + if (BreakConstructorInitializersBeforeComma && + Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon) { + Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma; + } - if (Space.Maximum != -1u) { - Space.Minimum = std::min(Space.Minimum, Space.Maximum); + if (!IsGoogleOrChromium) { + if (Style.PackConstructorInitializers == FormatStyle::PCIS_BinPack && + OnCurrentLine) { + Style.PackConstructorInitializers = OnNextLine + ? FormatStyle::PCIS_NextLine + : FormatStyle::PCIS_CurrentLine; + } + } else if (Style.PackConstructorInitializers == + FormatStyle::PCIS_NextLine) { + if (!OnCurrentLine) + Style.PackConstructorInitializers = FormatStyle::PCIS_BinPack; + else if (!OnNextLine) + Style.PackConstructorInitializers = FormatStyle::PCIS_CurrentLine; + } + + if (Style.LineEnding == FormatStyle::LE_DeriveLF) { + if (!DeriveLineEnding) + Style.LineEnding = UseCRLF ? FormatStyle::LE_CRLF : FormatStyle::LE_LF; + else if (UseCRLF) + Style.LineEnding = FormatStyle::LE_DeriveCRLF; + } + + if (Style.SpacesInParens != FormatStyle::SIPO_Custom && + (SpacesInParentheses || SpaceInEmptyParentheses || + SpacesInConditionalStatement || SpacesInCStyleCastParentheses)) { + if (SpacesInParentheses) { + // set all options except InCStyleCasts and InEmptyParentheses + // to true for backward compatibility. + Style.SpacesInParensOptions.InConditionalStatements = true; + Style.SpacesInParensOptions.InCStyleCasts = + SpacesInCStyleCastParentheses; + Style.SpacesInParensOptions.InEmptyParentheses = + SpaceInEmptyParentheses; + Style.SpacesInParensOptions.Other = true; + } else { + Style.SpacesInParensOptions = {}; + Style.SpacesInParensOptions.InConditionalStatements = + SpacesInConditionalStatement; + Style.SpacesInParensOptions.InCStyleCasts = + SpacesInCStyleCastParentheses; + Style.SpacesInParensOptions.InEmptyParentheses = + SpaceInEmptyParentheses; + } + Style.SpacesInParens = FormatStyle::SIPO_Custom; } } }; @@ -863,14 +1255,21 @@ std::string ParseErrorCategory::message(int EV) const { return "Unsuitable"; case ParseError::BinPackTrailingCommaConflict: return "trailing comma insertion cannot be used with bin packing"; + case ParseError::InvalidQualifierSpecified: + return "Invalid qualifier specified in QualifierOrder"; + case ParseError::DuplicateQualifierSpecified: + return "Duplicate qualifier specified in QualifierOrder"; + case ParseError::MissingQualifierType: + return "Missing type in QualifierOrder"; + case ParseError::MissingQualifierOrder: + return "Missing QualifierOrder"; } llvm_unreachable("unexpected parse error"); } -static FormatStyle expandPresets(const FormatStyle &Style) { - if (Style.BreakBeforeBraces == FormatStyle::BS_Custom) - return Style; - FormatStyle Expanded = Style; +static void expandPresetsBraceWrapping(FormatStyle &Expanded) { + if (Expanded.BreakBeforeBraces == FormatStyle::BS_Custom) + return; Expanded.BraceWrapping = {/*AfterCaseLabel=*/false, /*AfterClass=*/false, /*AfterControlStatement=*/FormatStyle::BWACS_Never, @@ -889,7 +1288,7 @@ static FormatStyle expandPresets(const FormatStyle &Style) { /*SplitEmptyFunction=*/true, /*SplitEmptyRecord=*/true, /*SplitEmptyNamespace=*/true}; - switch (Style.BreakBeforeBraces) { + switch (Expanded.BreakBeforeBraces) { case FormatStyle::BS_Linux: Expanded.BraceWrapping.AfterClass = true; Expanded.BraceWrapping.AfterFunction = true; @@ -902,7 +1301,6 @@ static FormatStyle expandPresets(const FormatStyle &Style) { Expanded.BraceWrapping.AfterStruct = true; Expanded.BraceWrapping.AfterUnion = true; Expanded.BraceWrapping.AfterExternBlock = true; - Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; Expanded.BraceWrapping.SplitEmptyFunction = true; Expanded.BraceWrapping.SplitEmptyRecord = false; break; @@ -922,7 +1320,6 @@ static FormatStyle expandPresets(const FormatStyle &Style) { Expanded.BraceWrapping.AfterStruct = true; Expanded.BraceWrapping.AfterUnion = true; Expanded.BraceWrapping.AfterExternBlock = true; - Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; Expanded.BraceWrapping.BeforeCatch = true; Expanded.BraceWrapping.BeforeElse = true; Expanded.BraceWrapping.BeforeLambdaBody = true; @@ -937,7 +1334,6 @@ static FormatStyle expandPresets(const FormatStyle &Style) { Expanded.BraceWrapping.AfterObjCDeclaration = true; Expanded.BraceWrapping.AfterStruct = true; Expanded.BraceWrapping.AfterExternBlock = true; - Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; Expanded.BraceWrapping.BeforeCatch = true; Expanded.BraceWrapping.BeforeElse = true; Expanded.BraceWrapping.BeforeLambdaBody = true; @@ -962,7 +1358,6 @@ static FormatStyle expandPresets(const FormatStyle &Style) { /*SplitEmptyFunction=*/true, /*SplitEmptyRecord=*/true, /*SplitEmptyNamespace=*/true}; - Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; break; case FormatStyle::BS_WebKit: Expanded.BraceWrapping.AfterFunction = true; @@ -970,7 +1365,38 @@ static FormatStyle expandPresets(const FormatStyle &Style) { default: break; } - return Expanded; +} + +static void expandPresetsSpaceBeforeParens(FormatStyle &Expanded) { + if (Expanded.SpaceBeforeParens == FormatStyle::SBPO_Custom) + return; + // Reset all flags + Expanded.SpaceBeforeParensOptions = {}; + Expanded.SpaceBeforeParensOptions.AfterPlacementOperator = true; + + switch (Expanded.SpaceBeforeParens) { + case FormatStyle::SBPO_ControlStatements: + Expanded.SpaceBeforeParensOptions.AfterControlStatements = true; + Expanded.SpaceBeforeParensOptions.AfterForeachMacros = true; + Expanded.SpaceBeforeParensOptions.AfterIfMacros = true; + break; + case FormatStyle::SBPO_ControlStatementsExceptControlMacros: + Expanded.SpaceBeforeParensOptions.AfterControlStatements = true; + break; + case FormatStyle::SBPO_NonEmptyParentheses: + Expanded.SpaceBeforeParensOptions.BeforeNonEmptyParentheses = true; + break; + default: + break; + } +} + +static void expandPresetsSpacesInParens(FormatStyle &Expanded) { + if (Expanded.SpacesInParens == FormatStyle::SIPO_Custom) + return; + assert(Expanded.SpacesInParens == FormatStyle::SIPO_Never); + // Reset all flags + Expanded.SpacesInParensOptions = {}; } FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { @@ -982,18 +1408,27 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align; LLVMStyle.AlignArrayOfStructures = FormatStyle::AIAS_None; LLVMStyle.AlignOperands = FormatStyle::OAS_Align; - LLVMStyle.AlignTrailingComments = true; - LLVMStyle.AlignConsecutiveAssignments = FormatStyle::ACS_None; - LLVMStyle.AlignConsecutiveBitFields = FormatStyle::ACS_None; - LLVMStyle.AlignConsecutiveDeclarations = FormatStyle::ACS_None; - LLVMStyle.AlignConsecutiveMacros = FormatStyle::ACS_None; + LLVMStyle.AlignConsecutiveAssignments = {}; + LLVMStyle.AlignConsecutiveAssignments.Enabled = false; + LLVMStyle.AlignConsecutiveAssignments.AcrossEmptyLines = false; + LLVMStyle.AlignConsecutiveAssignments.AcrossComments = false; + LLVMStyle.AlignConsecutiveAssignments.AlignCompound = false; + LLVMStyle.AlignConsecutiveAssignments.AlignFunctionPointers = false; + LLVMStyle.AlignConsecutiveAssignments.PadOperators = true; + LLVMStyle.AlignConsecutiveBitFields = {}; + LLVMStyle.AlignConsecutiveDeclarations = {}; + LLVMStyle.AlignConsecutiveMacros = {}; + LLVMStyle.AlignConsecutiveShortCaseStatements = {}; + LLVMStyle.AlignTrailingComments = {}; + LLVMStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Always; + LLVMStyle.AlignTrailingComments.OverEmptyLines = 0; LLVMStyle.AllowAllArgumentsOnNextLine = true; - LLVMStyle.AllowAllConstructorInitializersOnNextLine = true; LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true; - LLVMStyle.AllowShortEnumsOnASingleLine = true; - LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; LLVMStyle.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never; LLVMStyle.AllowShortCaseLabelsOnASingleLine = false; + LLVMStyle.AllowShortCompoundRequirementOnASingleLine = true; + LLVMStyle.AllowShortEnumsOnASingleLine = true; + LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All; LLVMStyle.AllowShortLoopsOnASingleLine = false; @@ -1002,12 +1437,10 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.AlwaysBreakBeforeMultilineStrings = false; LLVMStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_MultiLine; LLVMStyle.AttributeMacros.push_back("__capability"); + LLVMStyle.BitFieldColonSpacing = FormatStyle::BFCS_Both; LLVMStyle.BinPackArguments = true; LLVMStyle.BinPackParameters = true; - LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None; - LLVMStyle.BreakBeforeConceptDeclarations = true; - LLVMStyle.BreakBeforeTernaryOperators = true; - LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach; + LLVMStyle.BracedInitializerIndentWidth = std::nullopt; LLVMStyle.BraceWrapping = {/*AfterCaseLabel=*/false, /*AfterClass=*/false, /*AfterControlStatement=*/FormatStyle::BWACS_Never, @@ -1026,20 +1459,27 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { /*SplitEmptyFunction=*/true, /*SplitEmptyRecord=*/true, /*SplitEmptyNamespace=*/true}; - LLVMStyle.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; + LLVMStyle.BreakAdjacentStringLiterals = true; + LLVMStyle.BreakAfterAttributes = FormatStyle::ABS_Leave; LLVMStyle.BreakAfterJavaFieldAnnotations = false; + LLVMStyle.BreakArrays = true; + LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None; + LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach; + LLVMStyle.BreakBeforeConceptDeclarations = FormatStyle::BBCDS_Always; + LLVMStyle.BreakBeforeInlineASMColon = FormatStyle::BBIAS_OnlyMultiline; + LLVMStyle.AllowBreakBeforeNoexceptSpecifier = FormatStyle::BBNSS_Never; + LLVMStyle.BreakBeforeTernaryOperators = true; LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon; LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon; LLVMStyle.BreakStringLiterals = true; LLVMStyle.ColumnLimit = 80; LLVMStyle.CommentPragmas = "^ IWYU pragma:"; LLVMStyle.CompactNamespaces = false; - LLVMStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = false; LLVMStyle.ConstructorInitializerIndentWidth = 4; LLVMStyle.ContinuationIndentWidth = 4; LLVMStyle.Cpp11BracedListStyle = true; - LLVMStyle.DeriveLineEnding = true; LLVMStyle.DerivePointerAlignment = false; + LLVMStyle.DisableFormat = false; LLVMStyle.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Never; LLVMStyle.EmptyLineBeforeAccessModifier = FormatStyle::ELBAMS_LogicalBlock; LLVMStyle.ExperimentalAutoDetectBinPacking = false; @@ -1057,40 +1497,49 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.IndentAccessModifiers = false; LLVMStyle.IndentCaseLabels = false; LLVMStyle.IndentCaseBlocks = false; + LLVMStyle.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; LLVMStyle.IndentGotoLabels = true; LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None; - LLVMStyle.IndentRequires = false; - LLVMStyle.IndentWrappedFunctionNames = false; + LLVMStyle.IndentRequiresClause = true; LLVMStyle.IndentWidth = 2; - LLVMStyle.PPIndentWidth = -1; + LLVMStyle.IndentWrappedFunctionNames = false; + LLVMStyle.InsertBraces = false; + LLVMStyle.InsertNewlineAtEOF = false; LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None; + LLVMStyle.IntegerLiteralSeparator = { + /*Binary=*/0, /*BinaryMinDigits=*/0, + /*Decimal=*/0, /*DecimalMinDigits=*/0, + /*Hex=*/0, /*HexMinDigits=*/0}; LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave; LLVMStyle.JavaScriptWrapImports = true; - LLVMStyle.TabWidth = 8; + LLVMStyle.KeepEmptyLinesAtEOF = false; + LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true; LLVMStyle.LambdaBodyIndentation = FormatStyle::LBI_Signature; + LLVMStyle.LineEnding = FormatStyle::LE_DeriveLF; LLVMStyle.MaxEmptyLinesToKeep = 1; - LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true; LLVMStyle.NamespaceIndentation = FormatStyle::NI_None; LLVMStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Auto; LLVMStyle.ObjCBlockIndentWidth = 2; LLVMStyle.ObjCBreakBeforeNestedBlockParam = true; LLVMStyle.ObjCSpaceAfterProperty = false; LLVMStyle.ObjCSpaceBeforeProtocolList = true; + LLVMStyle.PackConstructorInitializers = FormatStyle::PCIS_BinPack; LLVMStyle.PointerAlignment = FormatStyle::PAS_Right; + LLVMStyle.PPIndentWidth = -1; + LLVMStyle.QualifierAlignment = FormatStyle::QAS_Leave; LLVMStyle.ReferenceAlignment = FormatStyle::RAS_Pointer; - LLVMStyle.ShortNamespaceLines = 1; - LLVMStyle.SpacesBeforeTrailingComments = 1; - LLVMStyle.Standard = FormatStyle::LS_Latest; - LLVMStyle.UseCRLF = false; - LLVMStyle.UseTab = FormatStyle::UT_Never; LLVMStyle.ReflowComments = true; - LLVMStyle.SpacesInParentheses = false; - LLVMStyle.SpacesInSquareBrackets = false; - LLVMStyle.SpaceInEmptyBlock = false; - LLVMStyle.SpaceInEmptyParentheses = false; - LLVMStyle.SpacesInContainerLiterals = true; - LLVMStyle.SpacesInCStyleCastParentheses = false; - LLVMStyle.SpacesInLineCommentPrefix = {/*Minimum=*/1, /*Maximum=*/-1u}; + LLVMStyle.RemoveBracesLLVM = false; + LLVMStyle.RemoveParentheses = FormatStyle::RPS_Leave; + LLVMStyle.RemoveSemicolon = false; + LLVMStyle.RequiresClausePosition = FormatStyle::RCPS_OwnLine; + LLVMStyle.RequiresExpressionIndentation = FormatStyle::REI_OuterScope; + LLVMStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Leave; + LLVMStyle.ShortNamespaceLines = 1; + LLVMStyle.SkipMacroDefinitionBody = false; + LLVMStyle.SortIncludes = FormatStyle::SI_CaseSensitive; + LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before; + LLVMStyle.SortUsingDeclarations = FormatStyle::SUD_LexicographicNumeric; LLVMStyle.SpaceAfterCStyleCast = false; LLVMStyle.SpaceAfterLogicalNot = false; LLVMStyle.SpaceAfterTemplateKeyword = true; @@ -1098,14 +1547,35 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.SpaceBeforeCaseColon = false; LLVMStyle.SpaceBeforeCtorInitializerColon = true; LLVMStyle.SpaceBeforeInheritanceColon = true; + LLVMStyle.SpaceBeforeJsonColon = false; LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements; + LLVMStyle.SpaceBeforeParensOptions = {}; + LLVMStyle.SpaceBeforeParensOptions.AfterControlStatements = true; + LLVMStyle.SpaceBeforeParensOptions.AfterForeachMacros = true; + LLVMStyle.SpaceBeforeParensOptions.AfterIfMacros = true; LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true; LLVMStyle.SpaceBeforeAssignmentOperators = true; LLVMStyle.SpaceBeforeCpp11BracedList = false; LLVMStyle.SpaceBeforeSquareBrackets = false; - LLVMStyle.BitFieldColonSpacing = FormatStyle::BFCS_Both; + LLVMStyle.SpaceInEmptyBlock = false; + LLVMStyle.SpacesBeforeTrailingComments = 1; LLVMStyle.SpacesInAngles = FormatStyle::SIAS_Never; - LLVMStyle.SpacesInConditionalStatement = false; + LLVMStyle.SpacesInContainerLiterals = true; + LLVMStyle.SpacesInLineCommentPrefix = {/*Minimum=*/1, /*Maximum=*/-1u}; + LLVMStyle.SpacesInParens = FormatStyle::SIPO_Never; + LLVMStyle.SpacesInSquareBrackets = false; + LLVMStyle.Standard = FormatStyle::LS_Latest; + LLVMStyle.StatementAttributeLikeMacros.push_back("Q_EMIT"); + LLVMStyle.StatementMacros.push_back("Q_UNUSED"); + LLVMStyle.StatementMacros.push_back("QT_REQUIRE_VERSION"); + LLVMStyle.TabWidth = 8; + LLVMStyle.UseTab = FormatStyle::UT_Never; + LLVMStyle.VerilogBreakBetweenInstancePorts = true; + LLVMStyle.WhitespaceSensitiveMacros.push_back("BOOST_PP_STRINGIZE"); + LLVMStyle.WhitespaceSensitiveMacros.push_back("CF_SWIFT_NAME"); + LLVMStyle.WhitespaceSensitiveMacros.push_back("NS_SWIFT_NAME"); + LLVMStyle.WhitespaceSensitiveMacros.push_back("PP_STRINGIZE"); + LLVMStyle.WhitespaceSensitiveMacros.push_back("STRINGIZE"); LLVMStyle.PenaltyBreakAssignment = prec::Assignment; LLVMStyle.PenaltyBreakComment = 300; @@ -1114,28 +1584,25 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.PenaltyExcessCharacter = 1000000; LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60; LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19; + LLVMStyle.PenaltyBreakOpenParenthesis = 0; + LLVMStyle.PenaltyBreakScopeResolution = 500; LLVMStyle.PenaltyBreakTemplateDeclaration = prec::Relational; LLVMStyle.PenaltyIndentedWhitespace = 0; - LLVMStyle.DisableFormat = false; - LLVMStyle.SortIncludes = FormatStyle::SI_CaseSensitive; - LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before; - LLVMStyle.SortUsingDeclarations = true; - LLVMStyle.StatementAttributeLikeMacros.push_back("Q_EMIT"); - LLVMStyle.StatementMacros.push_back("Q_UNUSED"); - LLVMStyle.StatementMacros.push_back("QT_REQUIRE_VERSION"); - LLVMStyle.WhitespaceSensitiveMacros.push_back("STRINGIZE"); - LLVMStyle.WhitespaceSensitiveMacros.push_back("PP_STRINGIZE"); - LLVMStyle.WhitespaceSensitiveMacros.push_back("BOOST_PP_STRINGIZE"); - LLVMStyle.WhitespaceSensitiveMacros.push_back("NS_SWIFT_NAME"); - LLVMStyle.WhitespaceSensitiveMacros.push_back("CF_SWIFT_NAME"); - // Defaults that differ when not C++. - if (Language == FormatStyle::LK_TableGen) { + switch (Language) { + case FormatStyle::LK_TableGen: LLVMStyle.SpacesInContainerLiterals = false; - } - if (LLVMStyle.isJson()) { + break; + case FormatStyle::LK_Json: LLVMStyle.ColumnLimit = 0; + break; + case FormatStyle::LK_Verilog: + LLVMStyle.IndentCaseLabels = true; + LLVMStyle.SpacesInContainerLiterals = false; + break; + default: + break; } return LLVMStyle; @@ -1158,7 +1625,6 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { GoogleStyle.AllowShortLoopsOnASingleLine = true; GoogleStyle.AlwaysBreakBeforeMultilineStrings = true; GoogleStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes; - GoogleStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true; GoogleStyle.DerivePointerAlignment = true; GoogleStyle.IncludeStyle.IncludeCategories = {{"^<ext/.*\\.h>", 2, 0, false}, {"^<.*\\.h>", 1, 0, false}, @@ -1171,6 +1637,7 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { GoogleStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Never; GoogleStyle.ObjCSpaceAfterProperty = false; GoogleStyle.ObjCSpaceBeforeProtocolList = true; + GoogleStyle.PackConstructorInitializers = FormatStyle::PCIS_NextLine; GoogleStyle.PointerAlignment = FormatStyle::PAS_Left; GoogleStyle.RawStringFormats = { { @@ -1215,6 +1682,7 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { /*BasedOnStyle=*/"google", }, }; + GoogleStyle.SpacesBeforeTrailingComments = 2; GoogleStyle.Standard = FormatStyle::LS_Auto; @@ -1224,7 +1692,8 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { if (Language == FormatStyle::LK_Java) { GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign; GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign; - GoogleStyle.AlignTrailingComments = false; + GoogleStyle.AlignTrailingComments = {}; + GoogleStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Never; GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; @@ -1311,7 +1780,7 @@ FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) { ChromiumStyle.ContinuationIndentWidth = 8; ChromiumStyle.IndentWidth = 4; // See styleguide for import groups: - // https://chromium.googlesource.com/chromium/src/+/master/styleguide/java/java.md#Import-Order + // https://chromium.googlesource.com/chromium/src/+/refs/heads/main/styleguide/java/java.md#Import-Order ChromiumStyle.JavaImportGroups = { "android", "androidx", @@ -1372,7 +1841,8 @@ FormatStyle getWebKitStyle() { Style.AccessModifierOffset = -4; Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign; Style.AlignOperands = FormatStyle::OAS_DontAlign; - Style.AlignTrailingComments = false; + Style.AlignTrailingComments = {}; + Style.AlignTrailingComments.Kind = FormatStyle::TCAS_Never; Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty; Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; Style.BreakBeforeBraces = FormatStyle::BS_WebKit; @@ -1420,7 +1890,6 @@ FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language) { Style.BraceWrapping.AfterObjCDeclaration = true; Style.BraceWrapping.AfterStruct = true; Style.BraceWrapping.AfterExternBlock = true; - Style.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; Style.BraceWrapping.BeforeCatch = true; Style.BraceWrapping.BeforeElse = true; Style.BraceWrapping.BeforeWhile = false; @@ -1435,42 +1904,85 @@ FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language) { return Style; } +FormatStyle getClangFormatStyle() { + FormatStyle Style = getLLVMStyle(); + Style.InsertBraces = true; + Style.InsertNewlineAtEOF = true; + Style.LineEnding = FormatStyle::LE_LF; + Style.RemoveBracesLLVM = true; + Style.RemoveParentheses = FormatStyle::RPS_ReturnStatement; + return Style; +} + FormatStyle getNoStyle() { FormatStyle NoStyle = getLLVMStyle(); NoStyle.DisableFormat = true; NoStyle.SortIncludes = FormatStyle::SI_Never; - NoStyle.SortUsingDeclarations = false; + NoStyle.SortUsingDeclarations = FormatStyle::SUD_Never; return NoStyle; } bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language, FormatStyle *Style) { - if (Name.equals_insensitive("llvm")) { + if (Name.equals_insensitive("llvm")) *Style = getLLVMStyle(Language); - } else if (Name.equals_insensitive("chromium")) { + else if (Name.equals_insensitive("chromium")) *Style = getChromiumStyle(Language); - } else if (Name.equals_insensitive("mozilla")) { + else if (Name.equals_insensitive("mozilla")) *Style = getMozillaStyle(); - } else if (Name.equals_insensitive("google")) { + else if (Name.equals_insensitive("google")) *Style = getGoogleStyle(Language); - } else if (Name.equals_insensitive("webkit")) { + else if (Name.equals_insensitive("webkit")) *Style = getWebKitStyle(); - } else if (Name.equals_insensitive("gnu")) { + else if (Name.equals_insensitive("gnu")) *Style = getGNUStyle(); - } else if (Name.equals_insensitive("microsoft")) { + else if (Name.equals_insensitive("microsoft")) *Style = getMicrosoftStyle(Language); - } else if (Name.equals_insensitive("none")) { + else if (Name.equals_insensitive("clang-format")) + *Style = getClangFormatStyle(); + else if (Name.equals_insensitive("none")) *Style = getNoStyle(); - } else if (Name.equals_insensitive("inheritparentconfig")) { + else if (Name.equals_insensitive("inheritparentconfig")) Style->InheritsParentConfig = true; - } else { + else return false; - } Style->Language = Language; return true; } +ParseError validateQualifierOrder(FormatStyle *Style) { + // If its empty then it means don't do anything. + if (Style->QualifierOrder.empty()) + return ParseError::MissingQualifierOrder; + + // Ensure the list contains only currently valid qualifiers. + for (const auto &Qualifier : Style->QualifierOrder) { + if (Qualifier == "type") + continue; + auto token = + LeftRightQualifierAlignmentFixer::getTokenFromQualifier(Qualifier); + if (token == tok::identifier) + return ParseError::InvalidQualifierSpecified; + } + + // Ensure the list is unique (no duplicates). + std::set<std::string> UniqueQualifiers(Style->QualifierOrder.begin(), + Style->QualifierOrder.end()); + if (Style->QualifierOrder.size() != UniqueQualifiers.size()) { + LLVM_DEBUG(llvm::dbgs() + << "Duplicate Qualifiers " << Style->QualifierOrder.size() + << " vs " << UniqueQualifiers.size() << "\n"); + return ParseError::DuplicateQualifierSpecified; + } + + // Ensure the list has 'type' in it. + if (!llvm::is_contained(Style->QualifierOrder, "type")) + return ParseError::MissingQualifierType; + + return ParseError::Success; +} + std::error_code parseConfiguration(llvm::MemoryBufferRef Config, FormatStyle *Style, bool AllowUnknownOptions, llvm::SourceMgr::DiagHandlerTy DiagHandler, @@ -1479,7 +1991,7 @@ std::error_code parseConfiguration(llvm::MemoryBufferRef Config, FormatStyle::LanguageKind Language = Style->Language; assert(Language != FormatStyle::LK_None); if (Config.getBuffer().trim().empty()) - return make_error_code(ParseError::Error); + return make_error_code(ParseError::Success); Style->StyleSet.Clear(); std::vector<FormatStyle> Styles; llvm::yaml::Input Input(Config, /*Ctxt=*/nullptr, DiagHandler, @@ -1513,10 +2025,10 @@ std::error_code parseConfiguration(llvm::MemoryBufferRef Config, // configuration (which can only be at slot 0) after it. FormatStyle::FormatStyleSet StyleSet; bool LanguageFound = false; - for (int i = Styles.size() - 1; i >= 0; --i) { - if (Styles[i].Language != FormatStyle::LK_None) - StyleSet.Add(Styles[i]); - if (Styles[i].Language == Language) + for (const FormatStyle &Style : llvm::reverse(Styles)) { + if (Style.Language != FormatStyle::LK_None) + StyleSet.Add(Style); + if (Style.Language == Language) LanguageFound = true; } if (!LanguageFound) { @@ -1532,6 +2044,8 @@ std::error_code parseConfiguration(llvm::MemoryBufferRef Config, // See comment on FormatStyle::TSC_Wrapped. return make_error_code(ParseError::BinPackTrailingCommaConflict); } + if (Style->QualifierAlignment != FormatStyle::QAS_Leave) + return make_error_code(validateQualifierOrder(Style)); return make_error_code(ParseError::Success); } @@ -1541,18 +2055,22 @@ std::string configurationAsText(const FormatStyle &Style) { llvm::yaml::Output Output(Stream); // We use the same mapping method for input and output, so we need a non-const // reference here. - FormatStyle NonConstStyle = expandPresets(Style); + FormatStyle NonConstStyle = Style; + expandPresetsBraceWrapping(NonConstStyle); + expandPresetsSpaceBeforeParens(NonConstStyle); + expandPresetsSpacesInParens(NonConstStyle); Output << NonConstStyle; + return Stream.str(); } -llvm::Optional<FormatStyle> +std::optional<FormatStyle> FormatStyle::FormatStyleSet::Get(FormatStyle::LanguageKind Language) const { if (!Styles) - return None; + return std::nullopt; auto It = Styles->find(Language); if (It == Styles->end()) - return None; + return std::nullopt; FormatStyle Style = It->second; Style.StyleSet = *this; return Style; @@ -1571,13 +2089,212 @@ void FormatStyle::FormatStyleSet::Add(FormatStyle Style) { void FormatStyle::FormatStyleSet::Clear() { Styles.reset(); } -llvm::Optional<FormatStyle> +std::optional<FormatStyle> FormatStyle::GetLanguageStyle(FormatStyle::LanguageKind Language) const { return StyleSet.Get(Language); } namespace { +class ParensRemover : public TokenAnalyzer { +public: + ParensRemover(const Environment &Env, const FormatStyle &Style) + : TokenAnalyzer(Env, Style) {} + + std::pair<tooling::Replacements, unsigned> + analyze(TokenAnnotator &Annotator, + SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, + FormatTokenLexer &Tokens) override { + AffectedRangeMgr.computeAffectedLines(AnnotatedLines); + tooling::Replacements Result; + removeParens(AnnotatedLines, Result); + return {Result, 0}; + } + +private: + void removeParens(SmallVectorImpl<AnnotatedLine *> &Lines, + tooling::Replacements &Result) { + const auto &SourceMgr = Env.getSourceManager(); + for (auto *Line : Lines) { + removeParens(Line->Children, Result); + if (!Line->Affected) + continue; + for (const auto *Token = Line->First; Token && !Token->Finalized; + Token = Token->Next) { + if (!Token->Optional || !Token->isOneOf(tok::l_paren, tok::r_paren)) + continue; + auto *Next = Token->Next; + assert(Next && Next->isNot(tok::eof)); + SourceLocation Start; + if (Next->NewlinesBefore == 0) { + Start = Token->Tok.getLocation(); + Next->WhitespaceRange = Token->WhitespaceRange; + } else { + Start = Token->WhitespaceRange.getBegin(); + } + const auto &Range = + CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc()); + cantFail(Result.add(tooling::Replacement(SourceMgr, Range, " "))); + } + } + } +}; + +class BracesInserter : public TokenAnalyzer { +public: + BracesInserter(const Environment &Env, const FormatStyle &Style) + : TokenAnalyzer(Env, Style) {} + + std::pair<tooling::Replacements, unsigned> + analyze(TokenAnnotator &Annotator, + SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, + FormatTokenLexer &Tokens) override { + AffectedRangeMgr.computeAffectedLines(AnnotatedLines); + tooling::Replacements Result; + insertBraces(AnnotatedLines, Result); + return {Result, 0}; + } + +private: + void insertBraces(SmallVectorImpl<AnnotatedLine *> &Lines, + tooling::Replacements &Result) { + const auto &SourceMgr = Env.getSourceManager(); + int OpeningBraceSurplus = 0; + for (AnnotatedLine *Line : Lines) { + insertBraces(Line->Children, Result); + if (!Line->Affected && OpeningBraceSurplus == 0) + continue; + for (FormatToken *Token = Line->First; Token && !Token->Finalized; + Token = Token->Next) { + int BraceCount = Token->BraceCount; + if (BraceCount == 0) + continue; + std::string Brace; + if (BraceCount < 0) { + assert(BraceCount == -1); + if (!Line->Affected) + break; + Brace = Token->is(tok::comment) ? "\n{" : "{"; + ++OpeningBraceSurplus; + } else { + if (OpeningBraceSurplus == 0) + break; + if (OpeningBraceSurplus < BraceCount) + BraceCount = OpeningBraceSurplus; + Brace = '\n' + std::string(BraceCount, '}'); + OpeningBraceSurplus -= BraceCount; + } + Token->BraceCount = 0; + const auto Start = Token->Tok.getEndLoc(); + cantFail(Result.add(tooling::Replacement(SourceMgr, Start, 0, Brace))); + } + } + assert(OpeningBraceSurplus == 0); + } +}; + +class BracesRemover : public TokenAnalyzer { +public: + BracesRemover(const Environment &Env, const FormatStyle &Style) + : TokenAnalyzer(Env, Style) {} + + std::pair<tooling::Replacements, unsigned> + analyze(TokenAnnotator &Annotator, + SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, + FormatTokenLexer &Tokens) override { + AffectedRangeMgr.computeAffectedLines(AnnotatedLines); + tooling::Replacements Result; + removeBraces(AnnotatedLines, Result); + return {Result, 0}; + } + +private: + void removeBraces(SmallVectorImpl<AnnotatedLine *> &Lines, + tooling::Replacements &Result) { + const auto &SourceMgr = Env.getSourceManager(); + const auto End = Lines.end(); + for (auto I = Lines.begin(); I != End; ++I) { + const auto Line = *I; + removeBraces(Line->Children, Result); + if (!Line->Affected) + continue; + const auto NextLine = I + 1 == End ? nullptr : I[1]; + for (auto Token = Line->First; Token && !Token->Finalized; + Token = Token->Next) { + if (!Token->Optional) + continue; + if (!Token->isOneOf(tok::l_brace, tok::r_brace)) + continue; + auto Next = Token->Next; + assert(Next || Token == Line->Last); + if (!Next && NextLine) + Next = NextLine->First; + SourceLocation Start; + if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) { + Start = Token->Tok.getLocation(); + Next->WhitespaceRange = Token->WhitespaceRange; + } else { + Start = Token->WhitespaceRange.getBegin(); + } + const auto Range = + CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc()); + cantFail(Result.add(tooling::Replacement(SourceMgr, Range, ""))); + } + } + } +}; + +class SemiRemover : public TokenAnalyzer { +public: + SemiRemover(const Environment &Env, const FormatStyle &Style) + : TokenAnalyzer(Env, Style) {} + + std::pair<tooling::Replacements, unsigned> + analyze(TokenAnnotator &Annotator, + SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, + FormatTokenLexer &Tokens) override { + AffectedRangeMgr.computeAffectedLines(AnnotatedLines); + tooling::Replacements Result; + removeSemi(AnnotatedLines, Result); + return {Result, 0}; + } + +private: + void removeSemi(SmallVectorImpl<AnnotatedLine *> &Lines, + tooling::Replacements &Result) { + const auto &SourceMgr = Env.getSourceManager(); + const auto End = Lines.end(); + for (auto I = Lines.begin(); I != End; ++I) { + const auto Line = *I; + removeSemi(Line->Children, Result); + if (!Line->Affected) + continue; + const auto NextLine = I + 1 == End ? nullptr : I[1]; + for (auto Token = Line->First; Token && !Token->Finalized; + Token = Token->Next) { + if (!Token->Optional) + continue; + if (Token->isNot(tok::semi)) + continue; + auto Next = Token->Next; + assert(Next || Token == Line->Last); + if (!Next && NextLine) + Next = NextLine->First; + SourceLocation Start; + if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) { + Start = Token->Tok.getLocation(); + Next->WhitespaceRange = Token->WhitespaceRange; + } else { + Start = Token->WhitespaceRange.getBegin(); + } + const auto Range = + CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc()); + cantFail(Result.add(tooling::Replacement(SourceMgr, Range, ""))); + } + } + } +}; + class JavaScriptRequoter : public TokenAnalyzer { public: JavaScriptRequoter(const Environment &Env, const FormatStyle &Style) @@ -1609,10 +2326,11 @@ private: // NB: testing for not starting with a double quote to avoid // breaking `template strings`. (Style.JavaScriptQuotes == FormatStyle::JSQS_Single && - !Input.startswith("\"")) || + !Input.starts_with("\"")) || (Style.JavaScriptQuotes == FormatStyle::JSQS_Double && - !Input.startswith("\'"))) + !Input.starts_with("\'"))) { continue; + } // Change start and end quote. bool IsSingle = Style.JavaScriptQuotes == FormatStyle::JSQS_Single; @@ -1678,18 +2396,17 @@ public: tooling::Replacements Result; deriveLocalStyle(AnnotatedLines); AffectedRangeMgr.computeAffectedLines(AnnotatedLines); - for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { - Annotator.calculateFormattingInformation(*AnnotatedLines[i]); - } + for (AnnotatedLine *Line : AnnotatedLines) + Annotator.calculateFormattingInformation(*Line); Annotator.setCommentLineLevels(AnnotatedLines); WhitespaceManager Whitespaces( Env.getSourceManager(), Style, - Style.DeriveLineEnding - ? inputUsesCRLF( + Style.LineEnding > FormatStyle::LE_CRLF + ? WhitespaceManager::inputUsesCRLF( Env.getSourceManager().getBufferData(Env.getFileID()), - Style.UseCRLF) - : Style.UseCRLF); + Style.LineEnding == FormatStyle::LE_DeriveCRLF) + : Style.LineEnding == FormatStyle::LE_CRLF); ContinuationIndenter Indenter(Style, Tokens.getKeywords(), Env.getSourceManager(), Whitespaces, Encoding, BinPackInconclusiveFunctions); @@ -1710,24 +2427,19 @@ public: } private: - static bool inputUsesCRLF(StringRef Text, bool DefaultToCRLF) { - size_t LF = Text.count('\n'); - size_t CR = Text.count('\r') * 2; - return LF == CR ? DefaultToCRLF : CR > LF; - } - bool hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine *> &Lines) { for (const AnnotatedLine *Line : Lines) { if (hasCpp03IncompatibleFormat(Line->Children)) return true; for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) { - if (Tok->WhitespaceRange.getBegin() == Tok->WhitespaceRange.getEnd()) { + if (!Tok->hasWhitespaceBefore()) { if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener)) return true; if (Tok->is(TT_TemplateCloser) && - Tok->Previous->is(TT_TemplateCloser)) + Tok->Previous->is(TT_TemplateCloser)) { return true; + } } } } @@ -1739,12 +2451,22 @@ private: for (const AnnotatedLine *Line : Lines) { AlignmentDiff += countVariableAlignments(Line->Children); for (FormatToken *Tok = Line->First; Tok && Tok->Next; Tok = Tok->Next) { - if (!Tok->is(TT_PointerOrReference)) + if (Tok->isNot(TT_PointerOrReference)) continue; - bool SpaceBefore = - Tok->WhitespaceRange.getBegin() != Tok->WhitespaceRange.getEnd(); - bool SpaceAfter = Tok->Next->WhitespaceRange.getBegin() != - Tok->Next->WhitespaceRange.getEnd(); + // Don't treat space in `void foo() &&` as evidence. + if (const auto *Prev = Tok->getPreviousNonComment()) { + if (Prev->is(tok::r_paren) && Prev->MatchingParen) { + if (const auto *Func = + Prev->MatchingParen->getPreviousNonComment()) { + if (Func->isOneOf(TT_FunctionDeclarationName, TT_StartOfName, + TT_OverloadedOperator)) { + continue; + } + } + } + } + bool SpaceBefore = Tok->hasWhitespaceBefore(); + bool SpaceAfter = Tok->Next->hasWhitespaceBefore(); if (SpaceBefore && !SpaceAfter) ++AlignmentDiff; if (!SpaceBefore && SpaceAfter) @@ -1758,10 +2480,10 @@ private: deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { bool HasBinPackedFunction = false; bool HasOnePerLineFunction = false; - for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { - if (!AnnotatedLines[i]->First->Next) + for (AnnotatedLine *Line : AnnotatedLines) { + if (!Line->First->Next) continue; - FormatToken *Tok = AnnotatedLines[i]->First->Next; + FormatToken *Tok = Line->First->Next; while (Tok->Next) { if (Tok->is(PPK_BinPacked)) HasBinPackedFunction = true; @@ -1772,15 +2494,18 @@ private: } } if (Style.DerivePointerAlignment) { - Style.PointerAlignment = countVariableAlignments(AnnotatedLines) <= 0 - ? FormatStyle::PAS_Left - : FormatStyle::PAS_Right; + const auto NetRightCount = countVariableAlignments(AnnotatedLines); + if (NetRightCount > 0) + Style.PointerAlignment = FormatStyle::PAS_Right; + else if (NetRightCount < 0) + Style.PointerAlignment = FormatStyle::PAS_Left; Style.ReferenceAlignment = FormatStyle::RAS_Pointer; } - if (Style.Standard == FormatStyle::LS_Auto) + if (Style.Standard == FormatStyle::LS_Auto) { Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines) ? FormatStyle::LS_Latest : FormatStyle::LS_Cpp03; + } BinPackInconclusiveFunctions = HasBinPackedFunction || !HasOnePerLineFunction; } @@ -1833,8 +2558,9 @@ private: continue; if (!(FormatTok->is(tok::r_square) && Matching->is(TT_ArrayInitializerLSquare)) && - !(FormatTok->is(tok::r_brace) && Matching->is(TT_DictLiteral))) + !(FormatTok->is(tok::r_brace) && Matching->is(TT_DictLiteral))) { continue; + } FormatToken *Prev = FormatTok->getPreviousNonComment(); if (Prev->is(tok::comma) || Prev->is(tok::semi)) continue; @@ -1890,9 +2616,8 @@ public: private: void cleanupLine(AnnotatedLine *Line) { - for (auto *Child : Line->Children) { + for (auto *Child : Line->Children) cleanupLine(Child); - } if (Line->Affected) { cleanupRight(Line->First, tok::comma, tok::comma); @@ -1906,10 +2631,9 @@ private: } bool containsOnlyComments(const AnnotatedLine &Line) { - for (FormatToken *Tok = Line.First; Tok != nullptr; Tok = Tok->Next) { + for (FormatToken *Tok = Line.First; Tok; Tok = Tok->Next) if (Tok->isNot(tok::comment)) return false; - } return true; } @@ -1918,9 +2642,8 @@ private: std::set<unsigned> DeletedLines; for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { auto &Line = *AnnotatedLines[i]; - if (Line.startsWithNamespace()) { + if (Line.startsWithNamespace()) checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines); - } } for (auto Line : DeletedLines) { @@ -1957,8 +2680,9 @@ private: if (AnnotatedLines[CurrentLine]->startsWithNamespace()) { if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine, - DeletedLines)) + DeletedLines)) { return false; + } CurrentLine = NewLine; continue; } @@ -1979,12 +2703,12 @@ private: // Check if the empty namespace is actually affected by changed ranges. if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange( AnnotatedLines[InitLine]->First->Tok.getLocation(), - AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc()))) + AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc()))) { return false; + } - for (unsigned i = InitLine; i <= CurrentLine; ++i) { + for (unsigned i = InitLine; i <= CurrentLine; ++i) DeletedLines.insert(i); - } return true; } @@ -1997,10 +2721,12 @@ private: void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK, bool DeleteLeft) { auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * { - for (auto *Res = Tok.Next; Res; Res = Res->Next) - if (!Res->is(tok::comment) && - DeletedTokens.find(Res) == DeletedTokens.end()) + for (auto *Res = Tok.Next; Res; Res = Res->Next) { + if (Res->isNot(tok::comment) && + DeletedTokens.find(Res) == DeletedTokens.end()) { return Res; + } + } return nullptr; }; for (auto *Left = Start; Left;) { @@ -2038,7 +2764,7 @@ private: tooling::Replacements generateFixes() { tooling::Replacements Fixes; - std::vector<FormatToken *> Tokens; + SmallVector<FormatToken *> Tokens; std::copy(DeletedTokens.begin(), DeletedTokens.end(), std::back_inserter(Tokens)); @@ -2048,10 +2774,8 @@ private: unsigned Idx = 0; while (Idx < Tokens.size()) { unsigned St = Idx, End = Idx; - while ((End + 1) < Tokens.size() && - Tokens[End]->Next == Tokens[End + 1]) { - End++; - } + while ((End + 1) < Tokens.size() && Tokens[End]->Next == Tokens[End + 1]) + ++End; auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(), Tokens[End]->Tok.getEndLoc()); auto Err = @@ -2124,6 +2848,8 @@ private: "CGSizeMake", "CGVector", "CGVectorMake", + "FOUNDATION_EXPORT", // This is an alias for FOUNDATION_EXTERN. + "FOUNDATION_EXTERN", "NSAffineTransform", "NSArray", "NSAttributedString", @@ -2139,6 +2865,8 @@ private: "NSDecimalNumber", "NSDictionary", "NSEdgeInsets", + "NSError", + "NSErrorDomain", "NSHashTable", "NSIndexPath", "NSIndexSet", @@ -2178,15 +2906,17 @@ private: "NSURLQueryItem", "NSUUID", "NSValue", + "NS_ASSUME_NONNULL_BEGIN", "UIImage", "UIView", }; - for (auto Line : AnnotatedLines) { - if (Line->First && (Line->First->TokenText.startswith("#") || + for (auto *Line : AnnotatedLines) { + if (Line->First && (Line->First->TokenText.starts_with("#") || Line->First->TokenText == "__pragma" || - Line->First->TokenText == "_Pragma")) + Line->First->TokenText == "_Pragma")) { continue; + } for (const FormatToken *FormatTok = Line->First; FormatTok; FormatTok = FormatTok->Next) { if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) && @@ -2199,6 +2929,7 @@ private: FormatTok->TokenText)) || FormatTok->is(TT_ObjCStringLiteral) || FormatTok->isOneOf(Keywords.kw_NS_CLOSED_ENUM, Keywords.kw_NS_ENUM, + Keywords.kw_NS_ERROR_ENUM, Keywords.kw_NS_OPTIONS, TT_ObjCBlockLBrace, TT_ObjCBlockLParen, TT_ObjCDecl, TT_ObjCForIn, TT_ObjCMethodExpr, TT_ObjCMethodSpecifier, @@ -2233,7 +2964,7 @@ struct JavaImportDirective { StringRef Identifier; StringRef Text; unsigned Offset; - std::vector<StringRef> AssociatedCommentLines; + SmallVector<StringRef> AssociatedCommentLines; bool IsStatic; }; @@ -2242,10 +2973,11 @@ struct JavaImportDirective { // Determines whether 'Ranges' intersects with ('Start', 'End'). static bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start, unsigned End) { - for (auto Range : Ranges) { + for (const auto &Range : Ranges) { if (Range.getOffset() < End && - Range.getOffset() + Range.getLength() > Start) + Range.getOffset() + Range.getLength() > Start) { return true; + } } return false; } @@ -2286,7 +3018,7 @@ std::string replaceCRLF(const std::string &Code) { do { Pos = Code.find("\r\n", LastPos); if (Pos == LastPos) { - LastPos++; + ++LastPos; continue; } if (Pos == std::string::npos) { @@ -2313,16 +3045,14 @@ static void sortCppIncludes(const FormatStyle &Style, StringRef Code, tooling::Replacements &Replaces, unsigned *Cursor) { tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName); - unsigned IncludesBeginOffset = Includes.front().Offset; - unsigned IncludesEndOffset = + const unsigned IncludesBeginOffset = Includes.front().Offset; + const unsigned IncludesEndOffset = Includes.back().Offset + Includes.back().Text.size(); - unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset; + const unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset; if (!affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset)) return; - SmallVector<unsigned, 16> Indices; - for (unsigned i = 0, e = Includes.size(); i != e; ++i) { - Indices.push_back(i); - } + SmallVector<unsigned, 16> Indices = + llvm::to_vector<16>(llvm::seq<unsigned>(0, Includes.size())); if (Style.SortIncludes == FormatStyle::SI_CaseInsensitive) { llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) { @@ -2345,9 +3075,10 @@ static void sortCppIncludes(const FormatStyle &Style, unsigned CursorIndex; // The offset from cursor to the end of line. unsigned CursorToEOLOffset; - if (Cursor) + if (Cursor) { std::tie(CursorIndex, CursorToEOLOffset) = FindCursorIndex(Includes, Indices, *Cursor); + } // Deduplicate #includes. Indices.erase(std::unique(Indices.begin(), Indices.end(), @@ -2363,11 +3094,12 @@ static void sortCppIncludes(const FormatStyle &Style, // the entire block. Otherwise, no replacement is generated. // In case Style.IncldueStyle.IncludeBlocks != IBS_Preserve, this check is not // enough as additional newlines might be added or removed across #include - // blocks. This we handle below by generating the updated #imclude blocks and + // blocks. This we handle below by generating the updated #include blocks and // comparing it to the original. if (Indices.size() == Includes.size() && llvm::is_sorted(Indices) && - Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Preserve) + Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Preserve) { return; + } std::string result; for (unsigned Index : Indices) { @@ -2375,8 +3107,9 @@ static void sortCppIncludes(const FormatStyle &Style, result += "\n"; if (Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Regroup && - CurrentCategory != Includes[Index].Category) + CurrentCategory != Includes[Index].Category) { result += "\n"; + } } result += Includes[Index].Text; if (Cursor && CursorIndex == Index) @@ -2384,11 +3117,15 @@ static void sortCppIncludes(const FormatStyle &Style, CurrentCategory = Includes[Index].Category; } + if (Cursor && *Cursor >= IncludesEndOffset) + *Cursor += result.size() - IncludesBlockSize; + // If the #includes are out of order, we generate a single replacement fixing // the entire range of blocks. Otherwise, no replacement is generated. if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr( - IncludesBeginOffset, IncludesBlockSize)))) + IncludesBeginOffset, IncludesBlockSize)))) { return; + } auto Err = Replaces.add(tooling::Replacement( FileName, Includes.front().Offset, IncludesBlockSize, result)); @@ -2400,13 +3137,6 @@ static void sortCppIncludes(const FormatStyle &Style, } } -namespace { - -const char CppIncludeRegexPattern[] = - R"(^[\t\ ]*#[\t\ ]*(import|include)[^"<]*(["<][^">]*[">]))"; - -} // anonymous namespace - tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code, ArrayRef<tooling::Range> Ranges, StringRef FileName, @@ -2416,7 +3146,6 @@ tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code, .StartsWith("\xEF\xBB\xBF", 3) // UTF-8 BOM .Default(0); unsigned SearchFrom = 0; - llvm::Regex IncludeRegex(CppIncludeRegexPattern); SmallVector<StringRef, 4> Matches; SmallVector<IncludeDirective, 16> IncludesInBlock; @@ -2425,23 +3154,41 @@ tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code, // doesn't have hidden dependencies // (http://llvm.org/docs/CodingStandards.html#include-style). // - // FIXME: Do some sanity checking, e.g. edit distance of the base name, to fix + // FIXME: Do some validation, e.g. edit distance of the base name, to fix // cases where the first #include is unlikely to be the main header. tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName); bool FirstIncludeBlock = true; bool MainIncludeFound = false; bool FormattingOff = false; + // '[' must be the first and '-' the last character inside [...]. + llvm::Regex RawStringRegex( + "R\"([][A-Za-z0-9_{}#<>%:;.?*+/^&\\$|~!=,'-]*)\\("); + SmallVector<StringRef, 2> RawStringMatches; + std::string RawStringTermination = ")\""; + for (;;) { auto Pos = Code.find('\n', SearchFrom); StringRef Line = Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev); StringRef Trimmed = Line.trim(); - if (Trimmed == "// clang-format off" || Trimmed == "/* clang-format off */") + + // #includes inside raw string literals need to be ignored. + // or we will sort the contents of the string. + // Skip past until we think we are at the rawstring literal close. + if (RawStringRegex.match(Trimmed, &RawStringMatches)) { + std::string CharSequence = RawStringMatches[1].str(); + RawStringTermination = ")" + CharSequence + "\""; FormattingOff = true; - else if (Trimmed == "// clang-format on" || - Trimmed == "/* clang-format on */") + } + + if (Trimmed.contains(RawStringTermination)) + FormattingOff = false; + + if (isClangFormatOff(Trimmed)) + FormattingOff = true; + else if (isClangFormatOn(Trimmed)) FormattingOff = false; const bool EmptyLineSkipped = @@ -2450,10 +3197,19 @@ tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code, Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Regroup); - bool MergeWithNextLine = Trimmed.endswith("\\"); + bool MergeWithNextLine = Trimmed.ends_with("\\"); if (!FormattingOff && !MergeWithNextLine) { - if (IncludeRegex.match(Line, &Matches)) { + if (tooling::HeaderIncludes::IncludeRegex.match(Line, &Matches)) { StringRef IncludeName = Matches[2]; + if (Line.contains("/*") && !Line.contains("*/")) { + // #include with a start of a block comment, but without the end. + // Need to keep all the lines until the end of the comment together. + // FIXME: This is somehow simplified check that probably does not work + // correctly if there are multiple comments on a line. + Pos = Code.find("*/", SearchFrom); + Line = Code.substr( + Prev, (Pos != StringRef::npos ? Pos + 2 : Code.size()) - Prev); + } int Category = Categories.getIncludePriority( IncludeName, /*CheckMainHeader=*/!MainIncludeFound && FirstIncludeBlock); @@ -2467,7 +3223,7 @@ tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code, sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, Replaces, Cursor); IncludesInBlock.clear(); - if (Trimmed.startswith("#pragma hdrstop")) // Precompiled headers. + if (Trimmed.starts_with("#pragma hdrstop")) // Precompiled headers. FirstIncludeBlock = true; else FirstIncludeBlock = false; @@ -2494,8 +3250,8 @@ static unsigned findJavaImportGroup(const FormatStyle &Style, unsigned LongestMatchIndex = UINT_MAX; unsigned LongestMatchLength = 0; for (unsigned I = 0; I < Style.JavaImportGroups.size(); I++) { - std::string GroupPrefix = Style.JavaImportGroups[I]; - if (ImportIdentifier.startswith(GroupPrefix) && + const std::string &GroupPrefix = Style.JavaImportGroups[I]; + if (ImportIdentifier.starts_with(GroupPrefix) && GroupPrefix.length() > LongestMatchLength) { LongestMatchIndex = I; LongestMatchLength = GroupPrefix.length(); @@ -2519,13 +3275,14 @@ static void sortJavaImports(const FormatStyle &Style, unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset; if (!affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset)) return; - SmallVector<unsigned, 16> Indices; + + SmallVector<unsigned, 16> Indices = + llvm::to_vector<16>(llvm::seq<unsigned>(0, Imports.size())); SmallVector<unsigned, 16> JavaImportGroups; - for (unsigned i = 0, e = Imports.size(); i != e; ++i) { - Indices.push_back(i); - JavaImportGroups.push_back( - findJavaImportGroup(Style, Imports[i].Identifier)); - } + JavaImportGroups.reserve(Imports.size()); + for (const JavaImportDirective &Import : Imports) + JavaImportGroups.push_back(findJavaImportGroup(Style, Import.Identifier)); + bool StaticImportAfterNormalImport = Style.SortJavaStaticImport == FormatStyle::SJSIO_After; llvm::sort(Indices, [&](unsigned LHSI, unsigned RHSI) { @@ -2553,8 +3310,9 @@ static void sortJavaImports(const FormatStyle &Style, if (!result.empty()) { result += "\n"; if (CurrentIsStatic != Imports[Index].IsStatic || - CurrentImportGroup != JavaImportGroups[Index]) + CurrentImportGroup != JavaImportGroups[Index]) { result += "\n"; + } } for (StringRef CommentLine : Imports[Index].AssociatedCommentLines) { result += CommentLine; @@ -2568,8 +3326,9 @@ static void sortJavaImports(const FormatStyle &Style, // If the imports are out of order, we generate a single replacement fixing // the entire block. Otherwise, no replacement is generated. if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr( - Imports.front().Offset, ImportsBlockSize)))) + Imports.front().Offset, ImportsBlockSize)))) { return; + } auto Err = Replaces.add(tooling::Replacement(FileName, Imports.front().Offset, ImportsBlockSize, result)); @@ -2597,7 +3356,7 @@ tooling::Replacements sortJavaImports(const FormatStyle &Style, StringRef Code, llvm::Regex ImportRegex(JavaImportRegexPattern); SmallVector<StringRef, 4> Matches; SmallVector<JavaImportDirective, 16> ImportsInBlock; - std::vector<StringRef> AssociatedCommentLines; + SmallVector<StringRef> AssociatedCommentLines; bool FormattingOff = false; @@ -2607,9 +3366,9 @@ tooling::Replacements sortJavaImports(const FormatStyle &Style, StringRef Code, Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev); StringRef Trimmed = Line.trim(); - if (Trimmed == "// clang-format off") + if (isClangFormatOff(Trimmed)) FormattingOff = true; - else if (Trimmed == "// clang-format on") + else if (isClangFormatOn(Trimmed)) FormattingOff = false; if (ImportRegex.match(Line, &Matches)) { @@ -2621,9 +3380,8 @@ tooling::Replacements sortJavaImports(const FormatStyle &Style, StringRef Code, StringRef Static = Matches[1]; StringRef Identifier = Matches[2]; bool IsStatic = false; - if (Static.contains("static")) { + if (Static.contains("static")) IsStatic = true; - } ImportsInBlock.push_back( {Identifier, Line, Prev, AssociatedCommentLines, IsStatic}); AssociatedCommentLines.clear(); @@ -2648,7 +3406,7 @@ bool isMpegTS(StringRef Code) { return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47; } -bool isLikelyXml(StringRef Code) { return Code.ltrim().startswith("<"); } +bool isLikelyXml(StringRef Code) { return Code.ltrim().starts_with("<"); } tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code, ArrayRef<tooling::Range> Ranges, @@ -2659,8 +3417,9 @@ tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code, if (isLikelyXml(Code)) return Replaces; if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript && - isMpegTS(Code)) + isMpegTS(Code)) { return Replaces; + } if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript) return sortJavaScriptImports(Style, Code, Ranges, FileName); if (Style.Language == FormatStyle::LanguageKind::LK_Java) @@ -2718,8 +3477,8 @@ namespace { inline bool isHeaderInsertion(const tooling::Replacement &Replace) { return Replace.getOffset() == UINT_MAX && Replace.getLength() == 0 && - llvm::Regex(CppIncludeRegexPattern) - .match(Replace.getReplacementText()); + tooling::HeaderIncludes::IncludeRegex.match( + Replace.getReplacementText()); } inline bool isHeaderDeletion(const tooling::Replacement &Replace) { @@ -2759,7 +3518,7 @@ fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces, for (const auto &Header : HeadersToDelete) { tooling::Replacements Replaces = - Includes.remove(Header.trim("\"<>"), Header.startswith("<")); + Includes.remove(Header.trim("\"<>"), Header.starts_with("<")); for (const auto &R : Replaces) { auto Err = Result.add(R); if (Err) { @@ -2771,17 +3530,18 @@ fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces, } } - llvm::Regex IncludeRegex = llvm::Regex(CppIncludeRegexPattern); llvm::SmallVector<StringRef, 4> Matches; for (const auto &R : HeaderInsertions) { auto IncludeDirective = R.getReplacementText(); - bool Matched = IncludeRegex.match(IncludeDirective, &Matches); + bool Matched = + tooling::HeaderIncludes::IncludeRegex.match(IncludeDirective, &Matches); assert(Matched && "Header insertion replacement must have replacement text " "'#include ...'"); (void)Matched; auto IncludeName = Matches[2]; auto Replace = - Includes.insert(IncludeName.trim("\"<>"), IncludeName.startswith("<")); + Includes.insert(IncludeName.trim("\"<>"), IncludeName.starts_with("<"), + tooling::IncludeDirective::Include); if (Replace) { auto Err = Result.add(*Replace); if (Err) { @@ -2812,7 +3572,7 @@ cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces, // Make header insertion replacements insert new headers into correct blocks. tooling::Replacements NewReplaces = fixCppIncludeInsertions(Code, Replaces, Style); - return processReplacements(Cleanup, Code, NewReplaces, Style); + return cantFail(processReplacements(Cleanup, Code, NewReplaces, Style)); } namespace internal { @@ -2821,7 +3581,23 @@ reformat(const FormatStyle &Style, StringRef Code, ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn, unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName, FormattingAttemptStatus *Status) { - FormatStyle Expanded = expandPresets(Style); + FormatStyle Expanded = Style; + expandPresetsBraceWrapping(Expanded); + expandPresetsSpaceBeforeParens(Expanded); + expandPresetsSpacesInParens(Expanded); + Expanded.InsertBraces = false; + Expanded.RemoveBracesLLVM = false; + Expanded.RemoveParentheses = FormatStyle::RPS_Leave; + Expanded.RemoveSemicolon = false; + switch (Expanded.RequiresClausePosition) { + case FormatStyle::RCPS_SingleLine: + case FormatStyle::RCPS_WithPreceding: + Expanded.IndentRequiresClause = false; + break; + default: + break; + } + if (Expanded.DisableFormat) return {tooling::Replacements(), 0}; if (isLikelyXml(Code)) @@ -2832,59 +3608,118 @@ reformat(const FormatStyle &Style, StringRef Code, // JSON only needs the formatting passing. if (Style.isJson()) { std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size())); - auto Env = - std::make_unique<Environment>(Code, FileName, Ranges, FirstStartColumn, - NextStartColumn, LastStartColumn); + auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn, + NextStartColumn, LastStartColumn); + if (!Env) + return {}; // Perform the actual formatting pass. tooling::Replacements Replaces = Formatter(*Env, Style, Status).process().first; // add a replacement to remove the "x = " from the result. - if (!Replaces.add(tooling::Replacement(FileName, 0, 4, ""))) { - // apply the reformatting changes and the removal of "x = ". - if (applyAllReplacements(Code, Replaces)) { - return {Replaces, 0}; - } - } + Replaces = Replaces.merge( + tooling::Replacements(tooling::Replacement(FileName, 0, 4, ""))); + // apply the reformatting changes and the removal of "x = ". + if (applyAllReplacements(Code, Replaces)) + return {Replaces, 0}; return {tooling::Replacements(), 0}; } + auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn, + NextStartColumn, LastStartColumn); + if (!Env) + return {}; + typedef std::function<std::pair<tooling::Replacements, unsigned>( const Environment &)> AnalyzerPass; - SmallVector<AnalyzerPass, 4> Passes; - if (Style.Language == FormatStyle::LK_Cpp) { - if (Style.FixNamespaceComments) + SmallVector<AnalyzerPass, 16> Passes; + + Passes.emplace_back([&](const Environment &Env) { + return IntegerLiteralSeparatorFixer().process(Env, Expanded); + }); + + if (Style.isCpp()) { + if (Style.QualifierAlignment != FormatStyle::QAS_Leave) + addQualifierAlignmentFixerPasses(Expanded, Passes); + + if (Style.RemoveParentheses != FormatStyle::RPS_Leave) { + FormatStyle S = Expanded; + S.RemoveParentheses = Style.RemoveParentheses; + Passes.emplace_back([&, S = std::move(S)](const Environment &Env) { + return ParensRemover(Env, S).process(/*SkipAnnotation=*/true); + }); + } + + if (Style.InsertBraces) { + FormatStyle S = Expanded; + S.InsertBraces = true; + Passes.emplace_back([&, S = std::move(S)](const Environment &Env) { + return BracesInserter(Env, S).process(/*SkipAnnotation=*/true); + }); + } + + if (Style.RemoveBracesLLVM) { + FormatStyle S = Expanded; + S.RemoveBracesLLVM = true; + Passes.emplace_back([&, S = std::move(S)](const Environment &Env) { + return BracesRemover(Env, S).process(/*SkipAnnotation=*/true); + }); + } + + if (Style.RemoveSemicolon) { + FormatStyle S = Expanded; + S.RemoveSemicolon = true; + Passes.emplace_back([&, S = std::move(S)](const Environment &Env) { + return SemiRemover(Env, S).process(/*SkipAnnotation=*/true); + }); + } + + if (Style.FixNamespaceComments) { Passes.emplace_back([&](const Environment &Env) { return NamespaceEndCommentsFixer(Env, Expanded).process(); }); + } - if (Style.SortUsingDeclarations) + if (Style.SortUsingDeclarations != FormatStyle::SUD_Never) { Passes.emplace_back([&](const Environment &Env) { return UsingDeclarationsSorter(Env, Expanded).process(); }); + } + } + + if (Style.SeparateDefinitionBlocks != FormatStyle::SDS_Leave) { + Passes.emplace_back([&](const Environment &Env) { + return DefinitionBlockSeparator(Env, Expanded).process(); + }); } - if (Style.Language == FormatStyle::LK_JavaScript && - Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) + if (Style.Language == FormatStyle::LK_ObjC && + !Style.ObjCPropertyAttributeOrder.empty()) { Passes.emplace_back([&](const Environment &Env) { - return JavaScriptRequoter(Env, Expanded).process(); + return ObjCPropertyAttributeOrderFixer(Env, Expanded).process(); }); + } + + if (Style.isJavaScript() && + Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) { + Passes.emplace_back([&](const Environment &Env) { + return JavaScriptRequoter(Env, Expanded).process(/*SkipAnnotation=*/true); + }); + } Passes.emplace_back([&](const Environment &Env) { return Formatter(Env, Expanded, Status).process(); }); - if (Style.Language == FormatStyle::LK_JavaScript && - Style.InsertTrailingCommas == FormatStyle::TCS_Wrapped) + if (Style.isJavaScript() && + Style.InsertTrailingCommas == FormatStyle::TCS_Wrapped) { Passes.emplace_back([&](const Environment &Env) { return TrailingCommaInserter(Env, Expanded).process(); }); + } - auto Env = - std::make_unique<Environment>(Code, FileName, Ranges, FirstStartColumn, - NextStartColumn, LastStartColumn); - llvm::Optional<std::string> CurrentCode = None; + std::optional<std::string> CurrentCode; tooling::Replacements Fixes; unsigned Penalty = 0; for (size_t I = 0, E = Passes.size(); I < E; ++I) { @@ -2896,12 +3731,32 @@ reformat(const FormatStyle &Style, StringRef Code, Penalty += PassFixes.second; if (I + 1 < E) { CurrentCode = std::move(*NewCode); - Env = std::make_unique<Environment>( + Env = Environment::make( *CurrentCode, FileName, tooling::calculateRangesAfterReplacements(Fixes, Ranges), FirstStartColumn, NextStartColumn, LastStartColumn); + if (!Env) + return {}; + } + } + } + + if (Style.QualifierAlignment != FormatStyle::QAS_Leave) { + // Don't make replacements that replace nothing. QualifierAlignment can + // produce them if one of its early passes changes e.g. `const volatile` to + // `volatile const` and then a later pass changes it back again. + tooling::Replacements NonNoOpFixes; + for (const tooling::Replacement &Fix : Fixes) { + StringRef OriginalCode = Code.substr(Fix.getOffset(), Fix.getLength()); + if (!OriginalCode.equals(Fix.getReplacementText())) { + auto Err = NonNoOpFixes.add(Fix); + if (Err) { + llvm::errs() << "Error adding replacements : " + << llvm::toString(std::move(Err)) << "\n"; + } } } + Fixes = std::move(NonNoOpFixes); } return {Fixes, Penalty}; @@ -2925,7 +3780,10 @@ tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code, // cleanups only apply to C++ (they mostly concern ctor commas etc.) if (Style.Language != FormatStyle::LK_Cpp) return tooling::Replacements(); - return Cleaner(Environment(Code, FileName, Ranges), Style).process().first; + auto Env = Environment::make(Code, FileName, Ranges); + if (!Env) + return {}; + return Cleaner(*Env, Style).process().first; } tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, @@ -2942,18 +3800,20 @@ tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style, StringRef Code, ArrayRef<tooling::Range> Ranges, StringRef FileName) { - return NamespaceEndCommentsFixer(Environment(Code, FileName, Ranges), Style) - .process() - .first; + auto Env = Environment::make(Code, FileName, Ranges); + if (!Env) + return {}; + return NamespaceEndCommentsFixer(*Env, Style).process().first; } tooling::Replacements sortUsingDeclarations(const FormatStyle &Style, StringRef Code, ArrayRef<tooling::Range> Ranges, StringRef FileName) { - return UsingDeclarationsSorter(Environment(Code, FileName, Ranges), Style) - .process() - .first; + auto Env = Environment::make(Code, FileName, Ranges); + if (!Env) + return {}; + return UsingDeclarationsSorter(*Env, Style).process().first; } LangOptions getFormattingLangOpts(const FormatStyle &Style) { @@ -2970,6 +3830,10 @@ LangOptions getFormattingLangOpts(const FormatStyle &Style) { LangOpts.CPlusPlus17 = LexingStd >= FormatStyle::LS_Cpp17; LangOpts.CPlusPlus20 = LexingStd >= FormatStyle::LS_Cpp20; LangOpts.Char8 = LexingStd >= FormatStyle::LS_Cpp20; + // Turning on digraphs in standards before C++0x is error-prone, because e.g. + // the sequence "<::" will be unconditionally treated as "[:". + // Cf. Lexer::LexTokenInternal. + LangOpts.Digraphs = LexingStd >= FormatStyle::LS_Cpp11; LangOpts.LineComment = 1; bool AlternativeOperators = Style.isCpp(); @@ -2983,39 +3847,52 @@ LangOptions getFormattingLangOpts(const FormatStyle &Style) { } const char *StyleOptionHelpDescription = - "Coding style, currently supports:\n" - " LLVM, GNU, Google, Chromium, Microsoft, Mozilla, WebKit.\n" - "Use -style=file to load style configuration from\n" - ".clang-format file located in one of the parent\n" - "directories of the source file (or current\n" - "directory for stdin).\n" - "Use -style=\"{key: value, ...}\" to set specific\n" - "parameters, e.g.:\n" - " -style=\"{BasedOnStyle: llvm, IndentWidth: 8}\""; + "Set coding style. <string> can be:\n" + "1. A preset: LLVM, GNU, Google, Chromium, Microsoft,\n" + " Mozilla, WebKit.\n" + "2. 'file' to load style configuration from a\n" + " .clang-format file in one of the parent directories\n" + " of the source file (for stdin, see --assume-filename).\n" + " If no .clang-format file is found, falls back to\n" + " --fallback-style.\n" + " --style=file is the default.\n" + "3. 'file:<format_file_path>' to explicitly specify\n" + " the configuration file.\n" + "4. \"{key: value, ...}\" to set specific parameters, e.g.:\n" + " --style=\"{BasedOnStyle: llvm, IndentWidth: 8}\""; static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) { - if (FileName.endswith(".java")) + if (FileName.ends_with(".java")) return FormatStyle::LK_Java; - if (FileName.endswith_insensitive(".js") || - FileName.endswith_insensitive(".mjs") || - FileName.endswith_insensitive(".ts")) + if (FileName.ends_with_insensitive(".js") || + FileName.ends_with_insensitive(".mjs") || + FileName.ends_with_insensitive(".ts")) { return FormatStyle::LK_JavaScript; // (module) JavaScript or TypeScript. - if (FileName.endswith(".m") || FileName.endswith(".mm")) + } + if (FileName.ends_with(".m") || FileName.ends_with(".mm")) return FormatStyle::LK_ObjC; - if (FileName.endswith_insensitive(".proto") || - FileName.endswith_insensitive(".protodevel")) + if (FileName.ends_with_insensitive(".proto") || + FileName.ends_with_insensitive(".protodevel")) { return FormatStyle::LK_Proto; - if (FileName.endswith_insensitive(".textpb") || - FileName.endswith_insensitive(".pb.txt") || - FileName.endswith_insensitive(".textproto") || - FileName.endswith_insensitive(".asciipb")) + } + if (FileName.ends_with_insensitive(".textpb") || + FileName.ends_with_insensitive(".pb.txt") || + FileName.ends_with_insensitive(".textproto") || + FileName.ends_with_insensitive(".asciipb")) { return FormatStyle::LK_TextProto; - if (FileName.endswith_insensitive(".td")) + } + if (FileName.ends_with_insensitive(".td")) return FormatStyle::LK_TableGen; - if (FileName.endswith_insensitive(".cs")) + if (FileName.ends_with_insensitive(".cs")) return FormatStyle::LK_CSharp; - if (FileName.endswith_insensitive(".json")) + if (FileName.ends_with_insensitive(".json")) return FormatStyle::LK_Json; + if (FileName.ends_with_insensitive(".sv") || + FileName.ends_with_insensitive(".svh") || + FileName.ends_with_insensitive(".v") || + FileName.ends_with_insensitive(".vh")) { + return FormatStyle::LK_Verilog; + } return FormatStyle::LK_Cpp; } @@ -3037,38 +3914,76 @@ FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) { return GuessedLanguage; } +// Update StyleOptionHelpDescription above when changing this. const char *DefaultFormatStyle = "file"; const char *DefaultFallbackStyle = "LLVM"; +llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> +loadAndParseConfigFile(StringRef ConfigFile, llvm::vfs::FileSystem *FS, + FormatStyle *Style, bool AllowUnknownOptions) { + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = + FS->getBufferForFile(ConfigFile.str()); + if (auto EC = Text.getError()) + return EC; + if (auto EC = parseConfiguration(*Text.get(), Style, AllowUnknownOptions)) + return EC; + return Text; +} + llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName, StringRef FallbackStyleName, StringRef Code, llvm::vfs::FileSystem *FS, bool AllowUnknownOptions) { - if (!FS) { - FS = llvm::vfs::getRealFileSystem().get(); - } FormatStyle Style = getLLVMStyle(guessLanguage(FileName, Code)); - FormatStyle FallbackStyle = getNoStyle(); if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle)) - return make_string_error("Invalid fallback style \"" + FallbackStyleName); + return make_string_error("Invalid fallback style: " + FallbackStyleName); llvm::SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 1> ChildFormatTextToApply; - if (StyleName.startswith("{")) { + if (StyleName.starts_with("{")) { // Parse YAML/JSON style from the command line. StringRef Source = "<command-line>"; if (std::error_code ec = parseConfiguration(llvm::MemoryBufferRef(StyleName, Source), &Style, - AllowUnknownOptions)) + AllowUnknownOptions)) { return make_string_error("Error parsing -style: " + ec.message()); - if (Style.InheritsParentConfig) - ChildFormatTextToApply.emplace_back( - llvm::MemoryBuffer::getMemBuffer(StyleName, Source, false)); - else + } + + if (!Style.InheritsParentConfig) + return Style; + + ChildFormatTextToApply.emplace_back( + llvm::MemoryBuffer::getMemBuffer(StyleName, Source, false)); + } + + if (!FS) + FS = llvm::vfs::getRealFileSystem().get(); + assert(FS); + + // User provided clang-format file using -style=file:path/to/format/file. + if (!Style.InheritsParentConfig && + StyleName.starts_with_insensitive("file:")) { + auto ConfigFile = StyleName.substr(5); + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = + loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions); + if (auto EC = Text.getError()) { + return make_string_error("Error reading " + ConfigFile + ": " + + EC.message()); + } + + LLVM_DEBUG(llvm::dbgs() + << "Using configuration file " << ConfigFile << "\n"); + + if (!Style.InheritsParentConfig) return Style; + + // Search for parent configs starting from the parent directory of + // ConfigFile. + FileName = ConfigFile; + ChildFormatTextToApply.emplace_back(std::move(*Text)); } // If the style inherits the parent configuration it is a command line @@ -3081,24 +3996,33 @@ llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName, return Style; } - // Reset possible inheritance - Style.InheritsParentConfig = false; - - // Look for .clang-format/_clang-format file in the file's parent directories. - SmallString<128> UnsuitableConfigFiles; SmallString<128> Path(FileName); if (std::error_code EC = FS->makeAbsolute(Path)) return make_string_error(EC.message()); + // Reset possible inheritance + Style.InheritsParentConfig = false; + + auto dropDiagnosticHandler = [](const llvm::SMDiagnostic &, void *) {}; + + auto applyChildFormatTexts = [&](FormatStyle *Style) { + for (const auto &MemBuf : llvm::reverse(ChildFormatTextToApply)) { + auto EC = parseConfiguration(*MemBuf, Style, AllowUnknownOptions, + dropDiagnosticHandler); + // It was already correctly parsed. + assert(!EC); + static_cast<void>(EC); + } + }; + + // Look for .clang-format/_clang-format file in the file's parent directories. llvm::SmallVector<std::string, 2> FilesToLookFor; FilesToLookFor.push_back(".clang-format"); FilesToLookFor.push_back("_clang-format"); - auto dropDiagnosticHandler = [](const llvm::SMDiagnostic &, void *) {}; - + SmallString<128> UnsuitableConfigFiles; for (StringRef Directory = Path; !Directory.empty(); Directory = llvm::sys::path::parent_path(Directory)) { - auto Status = FS->status(Directory); if (!Status || Status->getType() != llvm::sys::fs::file_type::directory_file) { @@ -3111,81 +4035,85 @@ llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName, llvm::sys::path::append(ConfigFile, F); LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n"); - Status = FS->status(ConfigFile.str()); - - if (Status && - (Status->getType() == llvm::sys::fs::file_type::regular_file)) { - llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = - FS->getBufferForFile(ConfigFile.str()); - if (std::error_code EC = Text.getError()) - return make_string_error(EC.message()); - if (std::error_code ec = - parseConfiguration(*Text.get(), &Style, AllowUnknownOptions)) { - if (ec == ParseError::Unsuitable) { - if (!UnsuitableConfigFiles.empty()) - UnsuitableConfigFiles.append(", "); - UnsuitableConfigFiles.append(ConfigFile); - continue; - } + Status = FS->status(ConfigFile); + if (!Status || + Status->getType() != llvm::sys::fs::file_type::regular_file) { + continue; + } + + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = + loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions); + if (auto EC = Text.getError()) { + if (EC != ParseError::Unsuitable) { return make_string_error("Error reading " + ConfigFile + ": " + - ec.message()); + EC.message()); } - LLVM_DEBUG(llvm::dbgs() - << "Using configuration file " << ConfigFile << "\n"); + if (!UnsuitableConfigFiles.empty()) + UnsuitableConfigFiles.append(", "); + UnsuitableConfigFiles.append(ConfigFile); + continue; + } - if (!Style.InheritsParentConfig) { - if (ChildFormatTextToApply.empty()) - return Style; + LLVM_DEBUG(llvm::dbgs() + << "Using configuration file " << ConfigFile << "\n"); + if (!Style.InheritsParentConfig) { + if (!ChildFormatTextToApply.empty()) { LLVM_DEBUG(llvm::dbgs() << "Applying child configurations\n"); - - for (const auto &MemBuf : llvm::reverse(ChildFormatTextToApply)) { - auto Ec = parseConfiguration(*MemBuf, &Style, AllowUnknownOptions, - dropDiagnosticHandler); - // It was already correctly parsed. - assert(!Ec); - static_cast<void>(Ec); - } - - return Style; + applyChildFormatTexts(&Style); } + return Style; + } - LLVM_DEBUG(llvm::dbgs() << "Inherits parent configuration\n"); + LLVM_DEBUG(llvm::dbgs() << "Inherits parent configuration\n"); - // Reset inheritance of style - Style.InheritsParentConfig = false; + // Reset inheritance of style + Style.InheritsParentConfig = false; - ChildFormatTextToApply.emplace_back(std::move(*Text)); + ChildFormatTextToApply.emplace_back(std::move(*Text)); - // Breaking out of the inner loop, since we don't want to parse - // .clang-format AND _clang-format, if both exist. Then we continue the - // inner loop (parent directories) in search for the parent - // configuration. - break; - } + // Breaking out of the inner loop, since we don't want to parse + // .clang-format AND _clang-format, if both exist. Then we continue the + // outer loop (parent directories) in search for the parent + // configuration. + break; } } - if (!UnsuitableConfigFiles.empty()) + + if (!UnsuitableConfigFiles.empty()) { return make_string_error("Configuration file(s) do(es) not support " + getLanguageName(Style.Language) + ": " + UnsuitableConfigFiles); + } if (!ChildFormatTextToApply.empty()) { - assert(ChildFormatTextToApply.size() == 1); - LLVM_DEBUG(llvm::dbgs() - << "Applying child configuration on fallback style\n"); - - auto Ec = - parseConfiguration(*ChildFormatTextToApply.front(), &FallbackStyle, - AllowUnknownOptions, dropDiagnosticHandler); - // It was already correctly parsed. - assert(!Ec); - static_cast<void>(Ec); + << "Applying child configurations on fallback style\n"); + applyChildFormatTexts(&FallbackStyle); } return FallbackStyle; } +static bool isClangFormatOnOff(StringRef Comment, bool On) { + if (Comment == (On ? "/* clang-format on */" : "/* clang-format off */")) + return true; + + static const char ClangFormatOn[] = "// clang-format on"; + static const char ClangFormatOff[] = "// clang-format off"; + const unsigned Size = (On ? sizeof ClangFormatOn : sizeof ClangFormatOff) - 1; + + return Comment.starts_with(On ? ClangFormatOn : ClangFormatOff) && + (Comment.size() == Size || Comment[Size] == ':'); +} + +bool isClangFormatOn(StringRef Comment) { + return isClangFormatOnOff(Comment, /*On=*/true); +} + +bool isClangFormatOff(StringRef Comment) { + return isClangFormatOnOff(Comment, /*On=*/false); +} + } // namespace format } // namespace clang |