diff options
Diffstat (limited to 'clang/lib/Format/Format.cpp')
-rw-r--r-- | clang/lib/Format/Format.cpp | 235 |
1 files changed, 207 insertions, 28 deletions
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 2b860d2a25f7..085cca8853e6 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -19,6 +19,7 @@ #include "FormatInternal.h" #include "FormatTokenLexer.h" #include "NamespaceEndCommentsFixer.h" +#include "QualifierAlignmentFixer.h" #include "SortJavaScriptImports.h" #include "TokenAnalyzer.h" #include "TokenAnnotator.h" @@ -126,6 +127,16 @@ template <> struct ScalarEnumerationTraits<FormatStyle::ShortBlockStyle> { } }; +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 ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> { static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) { IO.enumCase(Value, "None", FormatStyle::SFS_None); @@ -147,7 +158,7 @@ template <> struct ScalarEnumerationTraits<FormatStyle::AlignConsecutiveStyle> { IO.enumCase(Value, "AcrossEmptyLinesAndComments", FormatStyle::ACS_AcrossEmptyLinesAndComments); - // For backward compability. + // For backward compatibility. IO.enumCase(Value, "true", FormatStyle::ACS_Consecutive); IO.enumCase(Value, "false", FormatStyle::ACS_None); } @@ -265,6 +276,17 @@ struct ScalarEnumerationTraits<FormatStyle::BreakInheritanceListStyle> { }; 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); + } +}; + +template <> struct ScalarEnumerationTraits<FormatStyle::EmptyLineAfterAccessModifierStyle> { static void enumeration(IO &IO, FormatStyle::EmptyLineAfterAccessModifierStyle &Value) { @@ -429,9 +451,8 @@ struct ScalarEnumerationTraits<FormatStyle::ReferenceAlignmentStyle> { }; template <> -struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensOptions> { - static void enumeration(IO &IO, - FormatStyle::SpaceBeforeParensOptions &Value) { +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); @@ -440,6 +461,7 @@ struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensOptions> { 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); @@ -552,8 +574,6 @@ template <> struct MappingTraits<FormatStyle> { IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments); IO.mapOptional("AllowAllArgumentsOnNextLine", Style.AllowAllArgumentsOnNextLine); - IO.mapOptional("AllowAllConstructorInitializersOnNextLine", - Style.AllowAllConstructorInitializersOnNextLine); IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine", Style.AllowAllParametersOfDeclarationOnNextLine); IO.mapOptional("AllowShortEnumsOnASingleLine", @@ -632,9 +652,18 @@ template <> struct MappingTraits<FormatStyle> { IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals); IO.mapOptional("ColumnLimit", Style.ColumnLimit); IO.mapOptional("CommentPragmas", Style.CommentPragmas); + 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("CompactNamespaces", Style.CompactNamespaces); - IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine", - Style.ConstructorInitializerAllOnOneLineOrOnePerLine); IO.mapOptional("ConstructorInitializerIndentWidth", Style.ConstructorInitializerIndentWidth); IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth); @@ -648,6 +677,41 @@ template <> struct MappingTraits<FormatStyle> { Style.EmptyLineBeforeAccessModifier); IO.mapOptional("ExperimentalAutoDetectBinPacking", Style.ExperimentalAutoDetectBinPacking); + + IO.mapOptional("PackConstructorInitializers", + Style.PackConstructorInitializers); + // 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. + StringRef BasedOn; + IO.mapOptional("BasedOnStyle", BasedOn); + const bool IsGoogleOrChromium = BasedOn.equals_insensitive("google") || + BasedOn.equals_insensitive("chromium"); + bool OnCurrentLine = IsGoogleOrChromium; + bool OnNextLine = true; + IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine", + OnCurrentLine); + IO.mapOptional("AllowAllConstructorInitializersOnNextLine", OnNextLine); + 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; + } + IO.mapOptional("FixNamespaceComments", Style.FixNamespaceComments); IO.mapOptional("ForEachMacros", Style.ForEachMacros); IO.mapOptional("IfMacros", Style.IfMacros); @@ -723,6 +787,7 @@ template <> struct MappingTraits<FormatStyle> { IO.mapOptional("SpaceBeforeInheritanceColon", Style.SpaceBeforeInheritanceColon); IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens); + IO.mapOptional("SpaceBeforeParensOptions", Style.SpaceBeforeParensOptions); IO.mapOptional("SpaceAroundPointerQualifiers", Style.SpaceAroundPointerQualifiers); IO.mapOptional("SpaceBeforeRangeBasedForLoopColon", @@ -781,6 +846,20 @@ template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> { } }; +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("BeforeNonEmptyParentheses", + Spacing.BeforeNonEmptyParentheses); + } +}; + template <> struct MappingTraits<FormatStyle::RawStringFormat> { static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) { IO.mapOptional("Language", Format.Language); @@ -863,14 +942,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 QualfierOrder"; + case ParseError::MissingQualifierType: + return "Missing type in QualfierOrder"; + case ParseError::MissingQualifierOrder: + return "Missing QualfierOrder"; } 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 +975,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; @@ -970,7 +1056,33 @@ 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 = {}; + + switch (Expanded.SpaceBeforeParens) { + case FormatStyle::SBPO_Never: + break; + 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; + case FormatStyle::SBPO_Always: + break; + default: + break; + } } FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { @@ -988,7 +1100,6 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.AlignConsecutiveDeclarations = FormatStyle::ACS_None; LLVMStyle.AlignConsecutiveMacros = FormatStyle::ACS_None; LLVMStyle.AllowAllArgumentsOnNextLine = true; - LLVMStyle.AllowAllConstructorInitializersOnNextLine = true; LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true; LLVMStyle.AllowShortEnumsOnASingleLine = true; LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; @@ -1034,15 +1145,19 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.ColumnLimit = 80; LLVMStyle.CommentPragmas = "^ IWYU pragma:"; LLVMStyle.CompactNamespaces = false; - LLVMStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = false; LLVMStyle.ConstructorInitializerIndentWidth = 4; LLVMStyle.ContinuationIndentWidth = 4; LLVMStyle.Cpp11BracedListStyle = true; + + // Off by default Qualifier ordering + LLVMStyle.QualifierAlignment = FormatStyle::QAS_Leave; + LLVMStyle.DeriveLineEnding = true; LLVMStyle.DerivePointerAlignment = false; LLVMStyle.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Never; LLVMStyle.EmptyLineBeforeAccessModifier = FormatStyle::ELBAMS_LogicalBlock; LLVMStyle.ExperimentalAutoDetectBinPacking = false; + LLVMStyle.PackConstructorInitializers = FormatStyle::PCIS_BinPack; LLVMStyle.FixNamespaceComments = true; LLVMStyle.ForEachMacros.push_back("foreach"); LLVMStyle.ForEachMacros.push_back("Q_FOREACH"); @@ -1099,6 +1214,9 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.SpaceBeforeCtorInitializerColon = true; LLVMStyle.SpaceBeforeInheritanceColon = true; LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements; + LLVMStyle.SpaceBeforeParensOptions.AfterControlStatements = true; + LLVMStyle.SpaceBeforeParensOptions.AfterForeachMacros = true; + LLVMStyle.SpaceBeforeParensOptions.AfterIfMacros = true; LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true; LLVMStyle.SpaceBeforeAssignmentOperators = true; LLVMStyle.SpaceBeforeCpp11BracedList = false; @@ -1158,7 +1276,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 +1288,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 = { { @@ -1311,7 +1429,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", @@ -1471,6 +1589,37 @@ bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind 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 unqiue (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; + } + + auto type = std::find(Style->QualifierOrder.begin(), + Style->QualifierOrder.end(), "type"); + if (type == Style->QualifierOrder.end()) + return ParseError::MissingQualifierType; + return ParseError::Success; +} + std::error_code parseConfiguration(llvm::MemoryBufferRef Config, FormatStyle *Style, bool AllowUnknownOptions, llvm::SourceMgr::DiagHandlerTy DiagHandler, @@ -1532,6 +1681,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,8 +1692,11 @@ 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); Output << NonConstStyle; + return Stream.str(); } @@ -2821,7 +2975,9 @@ 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); if (Expanded.DisableFormat) return {tooling::Replacements(), 0}; if (isLikelyXml(Code)) @@ -2833,8 +2989,10 @@ reformat(const FormatStyle &Style, StringRef Code, if (Style.isJson()) { std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size())); auto Env = - std::make_unique<Environment>(Code, FileName, Ranges, FirstStartColumn, + 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; @@ -2853,6 +3011,15 @@ reformat(const FormatStyle &Style, StringRef Code, AnalyzerPass; SmallVector<AnalyzerPass, 4> Passes; + if (Style.isCpp() && Style.QualifierAlignment != FormatStyle::QAS_Leave) { + Passes.emplace_back([&](const Environment &Env) { + return QualifierAlignmentFixer(Env, Expanded, Code, Ranges, + FirstStartColumn, NextStartColumn, + LastStartColumn, FileName) + .process(); + }); + } + if (Style.Language == FormatStyle::LK_Cpp) { if (Style.FixNamespaceComments) Passes.emplace_back([&](const Environment &Env) { @@ -2881,9 +3048,10 @@ reformat(const FormatStyle &Style, StringRef Code, return TrailingCommaInserter(Env, Expanded).process(); }); - 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 {}; llvm::Optional<std::string> CurrentCode = None; tooling::Replacements Fixes; unsigned Penalty = 0; @@ -2896,10 +3064,12 @@ 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 {}; } } } @@ -2925,7 +3095,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,7 +3115,10 @@ tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style, StringRef Code, ArrayRef<tooling::Range> Ranges, StringRef FileName) { - return NamespaceEndCommentsFixer(Environment(Code, FileName, Ranges), Style) + auto Env = Environment::make(Code, FileName, Ranges); + if (!Env) + return {}; + return NamespaceEndCommentsFixer(*Env, Style) .process() .first; } @@ -2951,7 +3127,10 @@ tooling::Replacements sortUsingDeclarations(const FormatStyle &Style, StringRef Code, ArrayRef<tooling::Range> Ranges, StringRef FileName) { - return UsingDeclarationsSorter(Environment(Code, FileName, Ranges), Style) + auto Env = Environment::make(Code, FileName, Ranges); + if (!Env) + return {}; + return UsingDeclarationsSorter(*Env, Style) .process() .first; } |