diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -195,23 +195,84 @@ -**AlignConsecutiveAssignments** (``bool``) - If ``true``, aligns consecutive assignments. +**AlignConsecutiveAssignments** (``AlignConsecutiveStyle``) + Style of aligning consecutive assignments. - This will align the assignment operators of consecutive lines. This - will result in formattings like + ``Consecutive`` will result in formattings like: .. code-block:: c++ - int aaaa = 12; - int b = 23; - int ccc = 23; + int a = 1; + int somelongname = 2; + double c = 3; -**AlignConsecutiveBitFields** (``bool``) - If ``true``, aligns consecutive bitfield members. + Possible values: + + * ``ACS_None`` (in configuration: ``None``) + Do not align assignments on consecutive lines. + + * ``ACS_Consecutive`` (in configuration: ``Consecutive``) + Align assignments on consecutive lines. This will result in + formattings like: + + .. code-block:: c++ + + int a = 1; + int somelongname = 2; + double c = 3; + + int d = 3; + /* A comment. */ + double e = 4; + + * ``ACS_AcrossEmptyLines`` (in configuration: ``AcrossEmptyLines``) + Same as ACS_Consecutive, but also spans over empty lines, e.g. + + .. code-block:: c++ + + int a = 1; + int somelongname = 2; + double c = 3; + + int d = 3; + /* A comment. */ + double e = 4; + + * ``ACS_AcrossComments`` (in configuration: ``AcrossComments``) + Same as ACS_Consecutive, but also spans over lines only containing + comments, e.g. + + .. code-block:: c++ + + int a = 1; + int somelongname = 2; + double c = 3; + + int d = 3; + /* A comment. */ + double e = 4; + + * ``ACS_AcrossEmptyLinesAndComments`` + (in configuration: ``AcrossEmptyLinesAndComments``) + + Same as ACS_Consecutive, but also spans over lines only containing + comments and empty lines, e.g. + + .. code-block:: c++ + + int a = 1; + int somelongname = 2; + double c = 3; + + int d = 3; + /* A comment. */ + double e = 4; + +**AlignConsecutiveBitFields** (``AlignConsecutiveStyle``) + Style of aligning consecutive bit field. - This will align the bitfield separators of consecutive lines. This - will result in formattings like + ``Consecutive`` will align the bitfield separators of consecutive lines. + This will result in formattings like: .. code-block:: c++ @@ -219,23 +280,146 @@ int b : 12; int ccc : 8; -**AlignConsecutiveDeclarations** (``bool``) - If ``true``, aligns consecutive declarations. + Possible values: + + * ``ACS_None`` (in configuration: ``None``) + Do not align bit fields on consecutive lines. + + * ``ACS_Consecutive`` (in configuration: ``Consecutive``) + Align bit fields on consecutive lines. This will result in + formattings like: + + .. code-block:: c++ + + int aaaa : 1; + int b : 12; + int ccc : 8; + + int d : 2; + /* A comment. */ + int ee : 3; + + * ``ACS_AcrossEmptyLines`` (in configuration: ``AcrossEmptyLines``) + Same as ACS_Consecutive, but also spans over empty lines, e.g. + + .. code-block:: c++ + + int aaaa : 1; + int b : 12; + int ccc : 8; + + int d : 2; + /* A comment. */ + int ee : 3; + + * ``ACS_AcrossComments`` (in configuration: ``AcrossComments``) + Same as ACS_Consecutive, but also spans over lines only containing + comments, e.g. + + .. code-block:: c++ + + int aaaa : 1; + int b : 12; + int ccc : 8; + + int d : 2; + /* A comment. */ + int ee : 3; + + * ``ACS_AcrossEmptyLinesAndComments`` + (in configuration: ``AcrossEmptyLinesAndComments``) + + Same as ACS_Consecutive, but also spans over lines only containing + comments and empty lines, e.g. + + .. code-block:: c++ + + int aaaa : 1; + int b : 12; + int ccc : 8; + + int d : 2; + /* A comment. */ + int ee : 3; + +**AlignConsecutiveDeclarations** (``AlignConsecutiveStyle``) + Style of aligning consecutive declarations. - This will align the declaration names of consecutive lines. This - will result in formattings like + ``Consecutive`` will align the declaration names of consecutive lines. + This will result in formattings like: .. code-block:: c++ int aaaa = 12; float b = 23; - std::string ccc = 23; + std::string ccc; -**AlignConsecutiveMacros** (``bool``) - If ``true``, aligns consecutive C/C++ preprocessor macros. + Possible values: + + * ``ACS_None`` (in configuration: ``None``) + Do not align bit declarations on consecutive lines. + + * ``ACS_Consecutive`` (in configuration: ``Consecutive``) + Align declarations on consecutive lines. This will result in + formattings like: + + .. code-block:: c++ + + int aaaa = 12; + float b = 23; + std::string ccc; + + int a = 42; + /* A comment. */ + bool c = false; + + * ``ACS_AcrossEmptyLines`` (in configuration: ``AcrossEmptyLines``) + Same as ACS_Consecutive, but also spans over empty lines, e.g. + + .. code-block:: c++ + + int aaaa = 12; + float b = 23; + std::string ccc; + + int a = 42; + /* A comment. */ + bool c = false; + + * ``ACS_AcrossComments`` (in configuration: ``AcrossComments``) + Same as ACS_Consecutive, but also spans over lines only containing + comments, e.g. + + .. code-block:: c++ + + int aaaa = 12; + float b = 23; + std::string ccc; + + int a = 42; + /* A comment. */ + bool c = false; + + * ``ACS_AcrossEmptyLinesAndComments`` + (in configuration: ``AcrossEmptyLinesAndComments``) + + Same as ACS_Consecutive, but also spans over lines only containing + comments and empty lines, e.g. + + .. code-block:: c++ + + int aaaa = 12; + float b = 23; + std::string ccc; + + int a = 42; + /* A comment. */ + bool c = false; + +**AlignConsecutiveMacros** (``AlignConsecutiveStyle``) + Style of aligning consecutive macro definitions. - This will align C/C++ preprocessor macros of consecutive lines. - Will result in formattings like + ``Consecutive`` will result in formattings like: .. code-block:: c++ @@ -245,6 +429,68 @@ #define foo(x) (x * x) #define bar(y, z) (y + z) + Possible values: + + * ``ACS_None`` (in configuration: ``None``) + Do not align macro definitions on consecutive lines. + + * ``ACS_Consecutive`` (in configuration: ``Consecutive``) + Align macro definitions on consecutive lines. This will result in + formattings like: + + .. code-block:: c++ + + #define SHORT_NAME 42 + #define LONGER_NAME 0x007f + #define EVEN_LONGER_NAME (2) + + #define foo(x) (x * x) + /* some comment */ + #define bar(y, z) (y + z) + + * ``ACS_AcrossEmptyLines`` (in configuration: ``AcrossEmptyLines``) + Same as ACS_Consecutive, but also spans over empty lines, e.g. + + .. code-block:: c++ + + #define SHORT_NAME 42 + #define LONGER_NAME 0x007f + #define EVEN_LONGER_NAME (2) + + #define foo(x) (x * x) + /* some comment */ + #define bar(y, z) (y + z) + + * ``ACS_AcrossComments`` (in configuration: ``AcrossComments``) + Same as ACS_Consecutive, but also spans over lines only containing + comments, e.g. + + .. code-block:: c++ + + #define SHORT_NAME 42 + #define LONGER_NAME 0x007f + #define EVEN_LONGER_NAME (2) + + #define foo(x) (x * x) + /* some comment */ + #define bar(y, z) (y + z) + + * ``ACS_AcrossEmptyLinesAndComments`` + (in configuration: ``AcrossEmptyLinesAndComments``) + + Same as ACS_Consecutive, but also spans over lines only containing + comments and empty lines, e.g. + + .. code-block:: c++ + + #define SHORT_NAME 42 + #define LONGER_NAME 0x007f + #define EVEN_LONGER_NAME (2) + + #define foo(x) (x * x) + /* some comment */ + #define bar(y, z) (y + z) + **AlignEscapedNewlines** (``EscapedNewlineAlignmentStyle``) Options for aligning backslashes in escaped newlines. diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -289,9 +289,11 @@ - Option ``IndentRequires`` has been added to indent the ``requires`` keyword in templates. + - Option ``BreakBeforeConceptDeclarations`` has been added to aid the formatting of concepts. -- Option ``IndentPragmas`` has been added to allow #pragma to indented with the current scope level. This is especially useful when using #pragma to mark OpenMP sections of code. +- Option ``IndentPragmas`` has been added to allow #pragma to indented with the current scope + level. This is especially useful when using #pragma to mark OpenMP sections of code. - Option ``SpaceBeforeCaseColon`` has been added to add a space before the colon in a case or default statement. @@ -300,6 +302,9 @@ macros which are not parsed as a type in front of a statement. See the documentation for an example. +- Options ``AlignConsecutiveAssignments``, ``AlignConsecutiveBitFields``, + ``AlignConsecutiveDeclarations`` and ``AlignConsecutiveMacros`` have been modified to allow + alignment across empty lines and/or comments. libclang -------- diff --git a/clang/docs/tools/dump_format_style.py b/clang/docs/tools/dump_format_style.py --- a/clang/docs/tools/dump_format_style.py +++ b/clang/docs/tools/dump_format_style.py @@ -42,7 +42,7 @@ def __str__(self): s = '**%s** (``%s``)\n%s' % (self.name, self.type, doxygen2rst(indent(self.comment, 2))) - if self.enum: + if self.enum and self.enum.values: s += indent('\n\nPossible values:\n\n%s\n' % self.enum, 2) if self.nested_struct: s += indent('\n\nNested configuration flags:\n\n%s\n' %self.nested_struct, @@ -104,13 +104,18 @@ doxygen2rst(indent(self.comment, 2))) def clean_comment_line(line): - match = re.match(r'^/// \\code(\{.(\w+)\})?$', line) + match = re.match(r'^/// (?P +)?\\code(\{.(?P\w+)\})?$', line) if match: - lang = match.groups()[1] + indent = match.group('indent') + if not indent: + indent = '' + lang = match.group('lang') if not lang: lang = 'c++' - return '\n.. code-block:: %s\n\n' % lang - if line == '/// \\endcode': + return '\n%s.. code-block:: %s\n\n' % (indent, lang) + + endcode_match = re.match(r'^/// +\\endcode$', line) + if endcode_match: return '' return line[4:] + '\n' @@ -184,7 +189,9 @@ state = State.InStruct enums[enum.name] = enum else: - raise Exception('Invalid format, expected enum field comment or };') + # Enum member without documentation. Must be documented where the enum + # is used. + pass elif state == State.InEnumMemberComment: if line.startswith('///'): comment += clean_comment_line(line) diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -84,10 +84,23 @@ /// brackets. BracketAlignmentStyle AlignAfterOpenBracket; - /// \brief If ``true``, aligns consecutive C/C++ preprocessor macros. + /// Styles for alignment of consecutive tokens. Tokens can be assignment signs + /// (see + /// ``AlignConsecutiveAssignments``), bitfield member separators (see + /// ``AlignConsecutiveBitFields``), names in declarations (see + /// ``AlignConsecutiveDeclarations``) or macro definitions (see + /// ``AlignConsecutiveMacros``). + enum AlignConsecutiveStyle { + ACS_None, + ACS_Consecutive, + ACS_AcrossEmptyLines, + ACS_AcrossComments, + ACS_AcrossEmptyLinesAndComments + }; + + /// Style of aligning consecutive macro definitions. /// - /// This will align C/C++ preprocessor macros of consecutive lines. - /// Will result in formattings like + /// ``Consecutive`` will result in formattings like: /// \code /// #define SHORT_NAME 42 /// #define LONGER_NAME 0x007f @@ -95,40 +108,271 @@ /// #define foo(x) (x * x) /// #define bar(y, z) (y + z) /// \endcode - bool AlignConsecutiveMacros; - - /// If ``true``, aligns consecutive assignments. /// - /// This will align the assignment operators of consecutive lines. This - /// will result in formattings like - /// \code - /// int aaaa = 12; - /// int b = 23; - /// int ccc = 23; - /// \endcode - bool AlignConsecutiveAssignments; - - /// If ``true``, aligns consecutive bitfield members. - /// - /// This will align the bitfield separators of consecutive lines. This - /// will result in formattings like + /// Possible values: + /// + /// * ``ACS_None`` (in configuration: ``None``) + /// Do not align macro definitions on consecutive lines. + /// + /// * ``ACS_Consecutive`` (in configuration: ``Consecutive``) + /// Align macro definitions on consecutive lines. This will result in + /// formattings like: + /// \code + /// #define SHORT_NAME 42 + /// #define LONGER_NAME 0x007f + /// #define EVEN_LONGER_NAME (2) + /// + /// #define foo(x) (x * x) + /// /* some comment */ + /// #define bar(y, z) (y + z) + /// \endcode + /// + /// * ``ACS_AcrossEmptyLines`` (in configuration: ``AcrossEmptyLines``) + /// Same as ACS_Consecutive, but also spans over empty lines, e.g. + /// \code + /// #define SHORT_NAME 42 + /// #define LONGER_NAME 0x007f + /// #define EVEN_LONGER_NAME (2) + /// + /// #define foo(x) (x * x) + /// /* some comment */ + /// #define bar(y, z) (y + z) + /// \endcode + /// + /// * ``ACS_AcrossComments`` (in configuration: ``AcrossComments``) + /// Same as ACS_Consecutive, but also spans over lines only containing + /// comments, e.g. + /// \code + /// #define SHORT_NAME 42 + /// #define LONGER_NAME 0x007f + /// #define EVEN_LONGER_NAME (2) + /// + /// #define foo(x) (x * x) + /// /* some comment */ + /// #define bar(y, z) (y + z) + /// \endcode + /// + /// * ``ACS_AcrossEmptyLinesAndComments`` + /// (in configuration: ``AcrossEmptyLinesAndComments``) + /// + /// Same as ACS_Consecutive, but also spans over lines only containing + /// comments and empty lines, e.g. + /// \code + /// #define SHORT_NAME 42 + /// #define LONGER_NAME 0x007f + /// #define EVEN_LONGER_NAME (2) + /// + /// #define foo(x) (x * x) + /// /* some comment */ + /// #define bar(y, z) (y + z) + /// \endcode + AlignConsecutiveStyle AlignConsecutiveMacros; + + /// Style of aligning consecutive assignments. + /// + /// ``Consecutive`` will result in formattings like: + /// \code + /// int a = 1; + /// int somelongname = 2; + /// double c = 3; + /// \endcode + /// + /// Possible values: + /// + /// * ``ACS_None`` (in configuration: ``None``) + /// Do not align assignments on consecutive lines. + /// + /// * ``ACS_Consecutive`` (in configuration: ``Consecutive``) + /// Align assignments on consecutive lines. This will result in + /// formattings like: + /// \code + /// int a = 1; + /// int somelongname = 2; + /// double c = 3; + /// + /// int d = 3; + /// /* A comment. */ + /// double e = 4; + /// \endcode + /// + /// * ``ACS_AcrossEmptyLines`` (in configuration: ``AcrossEmptyLines``) + /// Same as ACS_Consecutive, but also spans over empty lines, e.g. + /// \code + /// int a = 1; + /// int somelongname = 2; + /// double c = 3; + /// + /// int d = 3; + /// /* A comment. */ + /// double e = 4; + /// \endcode + /// + /// * ``ACS_AcrossComments`` (in configuration: ``AcrossComments``) + /// Same as ACS_Consecutive, but also spans over lines only containing + /// comments, e.g. + /// \code + /// int a = 1; + /// int somelongname = 2; + /// double c = 3; + /// + /// int d = 3; + /// /* A comment. */ + /// double e = 4; + /// \endcode + /// + /// * ``ACS_AcrossEmptyLinesAndComments`` + /// (in configuration: ``AcrossEmptyLinesAndComments``) + /// + /// Same as ACS_Consecutive, but also spans over lines only containing + /// comments and empty lines, e.g. + /// \code + /// int a = 1; + /// int somelongname = 2; + /// double c = 3; + /// + /// int d = 3; + /// /* A comment. */ + /// double e = 4; + /// \endcode + AlignConsecutiveStyle AlignConsecutiveAssignments; + + /// Style of aligning consecutive bit field. + /// + /// ``Consecutive`` will align the bitfield separators of consecutive lines. + /// This will result in formattings like: /// \code /// int aaaa : 1; /// int b : 12; /// int ccc : 8; /// \endcode - bool AlignConsecutiveBitFields; - - /// If ``true``, aligns consecutive declarations. /// - /// This will align the declaration names of consecutive lines. This - /// will result in formattings like + /// Possible values: + /// + /// * ``ACS_None`` (in configuration: ``None``) + /// Do not align bit fields on consecutive lines. + /// + /// * ``ACS_Consecutive`` (in configuration: ``Consecutive``) + /// Align bit fields on consecutive lines. This will result in + /// formattings like: + /// \code + /// int aaaa : 1; + /// int b : 12; + /// int ccc : 8; + /// + /// int d : 2; + /// /* A comment. */ + /// int ee : 3; + /// \endcode + /// + /// * ``ACS_AcrossEmptyLines`` (in configuration: ``AcrossEmptyLines``) + /// Same as ACS_Consecutive, but also spans over empty lines, e.g. + /// \code + /// int aaaa : 1; + /// int b : 12; + /// int ccc : 8; + /// + /// int d : 2; + /// /* A comment. */ + /// int ee : 3; + /// \endcode + /// + /// * ``ACS_AcrossComments`` (in configuration: ``AcrossComments``) + /// Same as ACS_Consecutive, but also spans over lines only containing + /// comments, e.g. + /// \code + /// int aaaa : 1; + /// int b : 12; + /// int ccc : 8; + /// + /// int d : 2; + /// /* A comment. */ + /// int ee : 3; + /// \endcode + /// + /// * ``ACS_AcrossEmptyLinesAndComments`` + /// (in configuration: ``AcrossEmptyLinesAndComments``) + /// + /// Same as ACS_Consecutive, but also spans over lines only containing + /// comments and empty lines, e.g. + /// \code + /// int aaaa : 1; + /// int b : 12; + /// int ccc : 8; + /// + /// int d : 2; + /// /* A comment. */ + /// int ee : 3; + /// \endcode + AlignConsecutiveStyle AlignConsecutiveBitFields; + + /// Style of aligning consecutive declarations. + /// + /// ``Consecutive`` will align the declaration names of consecutive lines. + /// This will result in formattings like: /// \code /// int aaaa = 12; /// float b = 23; - /// std::string ccc = 23; - /// \endcode - bool AlignConsecutiveDeclarations; + /// std::string ccc; + /// \endcode + /// + /// Possible values: + /// + /// * ``ACS_None`` (in configuration: ``None``) + /// Do not align bit declarations on consecutive lines. + /// + /// * ``ACS_Consecutive`` (in configuration: ``Consecutive``) + /// Align declarations on consecutive lines. This will result in + /// formattings like: + /// \code + /// int aaaa = 12; + /// float b = 23; + /// std::string ccc; + /// + /// int a = 42; + /// /* A comment. */ + /// bool c = false; + /// \endcode + /// + /// * ``ACS_AcrossEmptyLines`` (in configuration: ``AcrossEmptyLines``) + /// Same as ACS_Consecutive, but also spans over empty lines, e.g. + /// \code + /// int aaaa = 12; + /// float b = 23; + /// std::string ccc; + /// + /// int a = 42; + /// /* A comment. */ + /// bool c = false; + /// \endcode + /// + /// * ``ACS_AcrossComments`` (in configuration: ``AcrossComments``) + /// Same as ACS_Consecutive, but also spans over lines only containing + /// comments, e.g. + /// \code + /// int aaaa = 12; + /// float b = 23; + /// std::string ccc; + /// + /// int a = 42; + /// /* A comment. */ + /// bool c = false; + /// \endcode + /// + /// * ``ACS_AcrossEmptyLinesAndComments`` + /// (in configuration: ``AcrossEmptyLinesAndComments``) + /// + /// Same as ACS_Consecutive, but also spans over lines only containing + /// comments and empty lines, e.g. + /// \code + /// int aaaa = 12; + /// float b = 23; + /// std::string ccc; + /// + /// int a = 42; + /// /* A comment. */ + /// bool c = false; + /// \endcode + AlignConsecutiveStyle AlignConsecutiveDeclarations; /// Different styles for aligning escaped newlines. enum EscapedNewlineAlignmentStyle : unsigned char { @@ -2725,6 +2969,7 @@ AlignConsecutiveAssignments == R.AlignConsecutiveAssignments && AlignConsecutiveBitFields == R.AlignConsecutiveBitFields && AlignConsecutiveDeclarations == R.AlignConsecutiveDeclarations && + AlignConsecutiveMacros == R.AlignConsecutiveMacros && AlignEscapedNewlines == R.AlignEscapedNewlines && AlignOperands == R.AlignOperands && AlignTrailingComments == R.AlignTrailingComments && diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -128,6 +128,21 @@ } }; +template <> struct ScalarEnumerationTraits { + 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 { static void enumeration(IO &IO, FormatStyle::ShortIfStyle &Value) { IO.enumCase(Value, "Never", FormatStyle::SIS_Never); @@ -857,10 +872,10 @@ LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align; LLVMStyle.AlignOperands = FormatStyle::OAS_Align; LLVMStyle.AlignTrailingComments = true; - LLVMStyle.AlignConsecutiveAssignments = false; - LLVMStyle.AlignConsecutiveBitFields = false; - LLVMStyle.AlignConsecutiveDeclarations = false; - LLVMStyle.AlignConsecutiveMacros = false; + LLVMStyle.AlignConsecutiveAssignments = FormatStyle::ACS_None; + LLVMStyle.AlignConsecutiveBitFields = FormatStyle::ACS_None; + LLVMStyle.AlignConsecutiveDeclarations = FormatStyle::ACS_None; + LLVMStyle.AlignConsecutiveMacros = FormatStyle::ACS_None; LLVMStyle.AllowAllArgumentsOnNextLine = true; LLVMStyle.AllowAllConstructorInitializersOnNextLine = true; LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true; diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp --- a/clang/lib/Format/WhitespaceManager.cpp +++ b/clang/lib/Format/WhitespaceManager.cpp @@ -361,9 +361,10 @@ // that are split across multiple lines. See the test case in FormatTest.cpp // that mentions "split function parameter alignment" for an example of this. template -static unsigned AlignTokens(const FormatStyle &Style, F &&Matches, - SmallVector &Changes, - unsigned StartAt) { +static unsigned AlignTokens( + const FormatStyle &Style, F &&Matches, + SmallVector &Changes, unsigned StartAt, + const FormatStyle::AlignConsecutiveStyle &ACS = FormatStyle::ACS_None) { unsigned MinColumn = 0; unsigned MaxColumn = UINT_MAX; @@ -386,6 +387,9 @@ // Whether a matching token has been found on the current line. bool FoundMatchOnLine = false; + // Whether the current line consists purely of comments. + bool LineIsComment = true; + // Aligns a sequence of matching tokens, on the MinColumn column. // // Sequences start from the first matching token to align, and end at the @@ -411,19 +415,38 @@ if (Changes[i].NewlinesBefore != 0) { CommasBeforeMatch = 0; EndOfSequence = i; - // If there is a blank line, or if the last line didn't contain any - // matching token, the sequence ends here. - if (Changes[i].NewlinesBefore > 1 || !FoundMatchOnLine) + + // Whether to break the alignment sequence because of an empty line. + bool EmptyLineBreak = + (Changes[i].NewlinesBefore > 1) && + (ACS != FormatStyle::ACS_AcrossEmptyLines) && + (ACS != FormatStyle::ACS_AcrossEmptyLinesAndComments); + + // Whether to break the alignment sequence because of a line without a + // match. + bool NoMatchBreak = + !FoundMatchOnLine && + !(LineIsComment && + ((ACS == FormatStyle::ACS_AcrossComments) || + (ACS == FormatStyle::ACS_AcrossEmptyLinesAndComments))); + + if (EmptyLineBreak || NoMatchBreak) AlignCurrentSequence(); + // A new line starts, re-initialize line status tracking bools. FoundMatchOnLine = false; + LineIsComment = true; + } + + if (!Changes[i].Tok->is(tok::comment)) { + LineIsComment = false; } if (Changes[i].Tok->is(tok::comma)) { ++CommasBeforeMatch; } else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) { // Call AlignTokens recursively, skipping over this scope block. - unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i); + unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i, ACS); i = StoppedAt - 1; continue; } @@ -518,7 +541,7 @@ } void WhitespaceManager::alignConsecutiveMacros() { - if (!Style.AlignConsecutiveMacros) + if (Style.AlignConsecutiveMacros == FormatStyle::ACS_None) return; auto AlignMacrosMatches = [](const Change &C) { @@ -560,17 +583,41 @@ // Whether a matching token has been found on the current line. bool FoundMatchOnLine = false; + // Whether the current line consists only of comments + bool LineIsComment = true; + unsigned I = 0; for (unsigned E = Changes.size(); I != E; ++I) { if (Changes[I].NewlinesBefore != 0) { EndOfSequence = I; - // If there is a blank line, or if the last line didn't contain any - // matching token, the sequence ends here. - if (Changes[I].NewlinesBefore > 1 || !FoundMatchOnLine) + + // Whether to break the alignment sequence because of an empty line. + bool EmptyLineBreak = + (Changes[I].NewlinesBefore > 1) && + (Style.AlignConsecutiveMacros != FormatStyle::ACS_AcrossEmptyLines) && + (Style.AlignConsecutiveMacros != + FormatStyle::ACS_AcrossEmptyLinesAndComments); + + // Whether to break the alignment sequence because of a line without a + // match. + bool NoMatchBreak = + !FoundMatchOnLine && + !(LineIsComment && ((Style.AlignConsecutiveMacros == + FormatStyle::ACS_AcrossComments) || + (Style.AlignConsecutiveMacros == + FormatStyle::ACS_AcrossEmptyLinesAndComments))); + + if (EmptyLineBreak || NoMatchBreak) AlignMacroSequence(StartOfSequence, EndOfSequence, MinColumn, MaxColumn, FoundMatchOnLine, AlignMacrosMatches, Changes); + // A new line starts, re-initialize line status tracking bools. FoundMatchOnLine = false; + LineIsComment = true; + } + + if (!Changes[I].Tok->is(tok::comment)) { + LineIsComment = false; } if (!AlignMacrosMatches(Changes[I])) @@ -597,7 +644,7 @@ } void WhitespaceManager::alignConsecutiveAssignments() { - if (!Style.AlignConsecutiveAssignments) + if (Style.AlignConsecutiveAssignments == FormatStyle::ACS_None) return; AlignTokens( @@ -613,11 +660,11 @@ return C.Tok->is(tok::equal); }, - Changes, /*StartAt=*/0); + Changes, /*StartAt=*/0, Style.AlignConsecutiveAssignments); } void WhitespaceManager::alignConsecutiveBitFields() { - if (!Style.AlignConsecutiveBitFields) + if (Style.AlignConsecutiveBitFields == FormatStyle::ACS_None) return; AlignTokens( @@ -633,11 +680,11 @@ return C.Tok->is(TT_BitFieldColon); }, - Changes, /*StartAt=*/0); + Changes, /*StartAt=*/0, Style.AlignConsecutiveBitFields); } void WhitespaceManager::alignConsecutiveDeclarations() { - if (!Style.AlignConsecutiveDeclarations) + if (Style.AlignConsecutiveDeclarations == FormatStyle::ACS_None) return; // FIXME: Currently we don't handle properly the PointerAlignment: Right @@ -670,7 +717,7 @@ } return true; }, - Changes, /*StartAt=*/0); + Changes, /*StartAt=*/0, Style.AlignConsecutiveDeclarations); } void WhitespaceManager::alignChainedConditionals() { diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -11395,8 +11395,8 @@ "*/\n" "}", Tab)); - Tab.AlignConsecutiveAssignments = true; - Tab.AlignConsecutiveDeclarations = true; + Tab.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive; + Tab.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive; Tab.TabWidth = 4; Tab.IndentWidth = 4; verifyFormat("class Assign {\n" @@ -11634,8 +11634,8 @@ "*/\n" "}", Tab)); - Tab.AlignConsecutiveAssignments = true; - Tab.AlignConsecutiveDeclarations = true; + Tab.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive; + Tab.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive; Tab.TabWidth = 4; Tab.IndentWidth = 4; verifyFormat("class Assign {\n" @@ -12470,9 +12470,9 @@ TEST_F(FormatTest, AlignConsecutiveMacros) { FormatStyle Style = getLLVMStyle(); - Style.AlignConsecutiveAssignments = true; - Style.AlignConsecutiveDeclarations = true; - Style.AlignConsecutiveMacros = false; + Style.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive; + Style.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive; + Style.AlignConsecutiveMacros = FormatStyle::ACS_None; verifyFormat("#define a 3\n" "#define bbbb 4\n" @@ -12496,7 +12496,7 @@ "#define ffff(x, y) (x - y)", Style); - Style.AlignConsecutiveMacros = true; + Style.AlignConsecutiveMacros = FormatStyle::ACS_Consecutive; verifyFormat("#define a 3\n" "#define bbbb 4\n" "#define ccc (5)", @@ -12536,7 +12536,7 @@ "};", Style); - Style.AlignConsecutiveMacros = false; + Style.AlignConsecutiveMacros = FormatStyle::ACS_None; Style.ColumnLimit = 20; verifyFormat("#define a \\\n" @@ -12550,7 +12550,7 @@ " \"LLLLLLLL\"\n", Style); - Style.AlignConsecutiveMacros = true; + Style.AlignConsecutiveMacros = FormatStyle::ACS_Consecutive; verifyFormat("#define a \\\n" " \"aabbbbbbbbbbbb\"\n" "#define D \\\n" @@ -12561,12 +12561,766 @@ " \"FFFFFFFFFFFFF\" \\\n" " \"LLLLLLLL\"\n", Style); + + // Test across comments + Style.MaxEmptyLinesToKeep = 10; + Style.ReflowComments = false; + Style.AlignConsecutiveMacros = FormatStyle::ACS_AcrossComments; + EXPECT_EQ("#define a 3\n" + "// line comment\n" + "#define bbbb 4\n" + "#define ccc (5)", + format("#define a 3\n" + "// line comment\n" + "#define bbbb 4\n" + "#define ccc (5)", + Style)); + + EXPECT_EQ("#define a 3\n" + "/* block comment */\n" + "#define bbbb 4\n" + "#define ccc (5)", + format("#define a 3\n" + "/* block comment */\n" + "#define bbbb 4\n" + "#define ccc (5)", + Style)); + + EXPECT_EQ("#define a 3\n" + "/* multi-line *\n" + " * block comment */\n" + "#define bbbb 4\n" + "#define ccc (5)", + format("#define a 3\n" + "/* multi-line *\n" + " * block comment */\n" + "#define bbbb 4\n" + "#define ccc (5)", + Style)); + + EXPECT_EQ("#define a 3\n" + "// multi-line line comment\n" + "//\n" + "#define bbbb 4\n" + "#define ccc (5)", + format("#define a 3\n" + "// multi-line line comment\n" + "//\n" + "#define bbbb 4\n" + "#define ccc (5)", + Style)); + + EXPECT_EQ("#define a 3\n" + "// empty lines still break.\n" + "\n" + "#define bbbb 4\n" + "#define ccc (5)", + format("#define a 3\n" + "// empty lines still break.\n" + "\n" + "#define bbbb 4\n" + "#define ccc (5)", + Style)); + + // Test across empty lines + Style.AlignConsecutiveMacros = FormatStyle::ACS_AcrossEmptyLines; + EXPECT_EQ("#define a 3\n" + "\n" + "#define bbbb 4\n" + "#define ccc (5)", + format("#define a 3\n" + "\n" + "#define bbbb 4\n" + "#define ccc (5)", + Style)); + + EXPECT_EQ("#define a 3\n" + "\n" + "\n" + "\n" + "#define bbbb 4\n" + "#define ccc (5)", + format("#define a 3\n" + "\n" + "\n" + "\n" + "#define bbbb 4\n" + "#define ccc (5)", + Style)); + + EXPECT_EQ("#define a 3\n" + "// comments should break alignment\n" + "//\n" + "#define bbbb 4\n" + "#define ccc (5)", + format("#define a 3\n" + "// comments should break alignment\n" + "//\n" + "#define bbbb 4\n" + "#define ccc (5)", + Style)); + + // Test across empty lines and comments + Style.AlignConsecutiveMacros = FormatStyle::ACS_AcrossEmptyLinesAndComments; + verifyFormat("#define a 3\n" + "\n" + "// line comment\n" + "#define bbbb 4\n" + "#define ccc (5)", + Style); + + EXPECT_EQ("#define a 3\n" + "\n" + "\n" + "/* multi-line *\n" + " * block comment */\n" + "\n" + "\n" + "#define bbbb 4\n" + "#define ccc (5)", + format("#define a 3\n" + "\n" + "\n" + "/* multi-line *\n" + " * block comment */\n" + "\n" + "\n" + "#define bbbb 4\n" + "#define ccc (5)", + Style)); + + EXPECT_EQ("#define a 3\n" + "\n" + "\n" + "/* multi-line *\n" + " * block comment */\n" + "\n" + "\n" + "#define bbbb 4\n" + "#define ccc (5)", + format("#define a 3\n" + "\n" + "\n" + "/* multi-line *\n" + " * block comment */\n" + "\n" + "\n" + "#define bbbb 4\n" + "#define ccc (5)", + Style)); +} + +TEST_F(FormatTest, AlignConsecutiveAssignmentsAcrossEmptyLines) { + FormatStyle Alignment = getLLVMStyle(); + Alignment.AlignConsecutiveMacros = FormatStyle::ACS_Consecutive; + Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_AcrossEmptyLines; + + Alignment.MaxEmptyLinesToKeep = 10; + /* Test alignment across empty lines */ + EXPECT_EQ("int a = 5;\n" + "\n" + "int oneTwoThree = 123;", + format("int a = 5;\n" + "\n" + "int oneTwoThree= 123;", + Alignment)); + EXPECT_EQ("int a = 5;\n" + "int one = 1;\n" + "\n" + "int oneTwoThree = 123;", + format("int a = 5;\n" + "int one = 1;\n" + "\n" + "int oneTwoThree = 123;", + Alignment)); + EXPECT_EQ("int a = 5;\n" + "int one = 1;\n" + "\n" + "int oneTwoThree = 123;\n" + "int oneTwo = 12;", + format("int a = 5;\n" + "int one = 1;\n" + "\n" + "int oneTwoThree = 123;\n" + "int oneTwo = 12;", + Alignment)); + + /* Test across comments */ + EXPECT_EQ("int a = 5;\n" + "/* block comment */\n" + "int oneTwoThree = 123;", + format("int a = 5;\n" + "/* block comment */\n" + "int oneTwoThree=123;", + Alignment)); + + EXPECT_EQ("int a = 5;\n" + "// line comment\n" + "int oneTwoThree = 123;", + format("int a = 5;\n" + "// line comment\n" + "int oneTwoThree=123;", + Alignment)); + + /* Test across comments and newlines */ + EXPECT_EQ("int a = 5;\n" + "\n" + "/* block comment */\n" + "int oneTwoThree = 123;", + format("int a = 5;\n" + "\n" + "/* block comment */\n" + "int oneTwoThree=123;", + Alignment)); + + EXPECT_EQ("int a = 5;\n" + "\n" + "// line comment\n" + "int oneTwoThree = 123;", + format("int a = 5;\n" + "\n" + "// line comment\n" + "int oneTwoThree=123;", + Alignment)); +} + +TEST_F(FormatTest, AlignConsecutiveDeclarationsAcrossEmptyLinesAndComments) { + FormatStyle Alignment = getLLVMStyle(); + Alignment.AlignConsecutiveDeclarations = + FormatStyle::ACS_AcrossEmptyLinesAndComments; + Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_None; + + Alignment.MaxEmptyLinesToKeep = 10; + /* Test alignment across empty lines */ + EXPECT_EQ("int a = 5;\n" + "\n" + "float const oneTwoThree = 123;", + format("int a = 5;\n" + "\n" + "float const oneTwoThree = 123;", + Alignment)); + EXPECT_EQ("int a = 5;\n" + "float const one = 1;\n" + "\n" + "int oneTwoThree = 123;", + format("int a = 5;\n" + "float const one = 1;\n" + "\n" + "int oneTwoThree = 123;", + Alignment)); + + /* Test across comments */ + EXPECT_EQ("float const a = 5;\n" + "/* block comment */\n" + "int oneTwoThree = 123;", + format("float const a = 5;\n" + "/* block comment */\n" + "int oneTwoThree=123;", + Alignment)); + + EXPECT_EQ("float const a = 5;\n" + "// line comment\n" + "int oneTwoThree = 123;", + format("float const a = 5;\n" + "// line comment\n" + "int oneTwoThree=123;", + Alignment)); + + /* Test across comments and newlines */ + EXPECT_EQ("float const a = 5;\n" + "\n" + "/* block comment */\n" + "int oneTwoThree = 123;", + format("float const a = 5;\n" + "\n" + "/* block comment */\n" + "int oneTwoThree=123;", + Alignment)); + + EXPECT_EQ("float const a = 5;\n" + "\n" + "// line comment\n" + "int oneTwoThree = 123;", + format("float const a = 5;\n" + "\n" + "// line comment\n" + "int oneTwoThree=123;", + Alignment)); +} + +TEST_F(FormatTest, AlignConsecutiveBitFieldsAcrossEmptyLinesAndComments) { + FormatStyle Alignment = getLLVMStyle(); + Alignment.AlignConsecutiveBitFields = + FormatStyle::ACS_AcrossEmptyLinesAndComments; + + Alignment.MaxEmptyLinesToKeep = 10; + /* Test alignment across empty lines */ + EXPECT_EQ("int a : 5;\n" + "\n" + "int longbitfield : 6;", + format("int a : 5;\n" + "\n" + "int longbitfield : 6;", + Alignment)); + EXPECT_EQ("int a : 5;\n" + "int one : 1;\n" + "\n" + "int longbitfield : 6;", + format("int a : 5;\n" + "int one : 1;\n" + "\n" + "int longbitfield : 6;", + Alignment)); + + /* Test across comments */ + EXPECT_EQ("int a : 5;\n" + "/* block comment */\n" + "int longbitfield : 6;", + format("int a : 5;\n" + "/* block comment */\n" + "int longbitfield : 6;", + Alignment)); + EXPECT_EQ("int a : 5;\n" + "int one : 1;\n" + "// line comment\n" + "int longbitfield : 6;", + format("int a : 5;\n" + "int one : 1;\n" + "// line comment\n" + "int longbitfield : 6;", + Alignment)); + + /* Test across comments and newlines */ + EXPECT_EQ("int a : 5;\n" + "/* block comment */\n" + "\n" + "int longbitfield : 6;", + format("int a : 5;\n" + "/* block comment */\n" + "\n" + "int longbitfield : 6;", + Alignment)); + EXPECT_EQ("int a : 5;\n" + "int one : 1;\n" + "\n" + "// line comment\n" + "\n" + "int longbitfield : 6;", + format("int a : 5;\n" + "int one : 1;\n" + "\n" + "// line comment \n" + "\n" + "int longbitfield : 6;", + Alignment)); +} + +TEST_F(FormatTest, AlignConsecutiveAssignmentsAcrossComments) { + FormatStyle Alignment = getLLVMStyle(); + Alignment.AlignConsecutiveMacros = FormatStyle::ACS_Consecutive; + Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_AcrossComments; + + Alignment.MaxEmptyLinesToKeep = 10; + /* Test alignment across empty lines */ + EXPECT_EQ("int a = 5;\n" + "\n" + "int oneTwoThree = 123;", + format("int a = 5;\n" + "\n" + "int oneTwoThree= 123;", + Alignment)); + EXPECT_EQ("int a = 5;\n" + "int one = 1;\n" + "\n" + "int oneTwoThree = 123;", + format("int a = 5;\n" + "int one = 1;\n" + "\n" + "int oneTwoThree = 123;", + Alignment)); + + /* Test across comments */ + EXPECT_EQ("int a = 5;\n" + "/* block comment */\n" + "int oneTwoThree = 123;", + format("int a = 5;\n" + "/* block comment */\n" + "int oneTwoThree=123;", + Alignment)); + + EXPECT_EQ("int a = 5;\n" + "// line comment\n" + "int oneTwoThree = 123;", + format("int a = 5;\n" + "// line comment\n" + "int oneTwoThree=123;", + Alignment)); + + EXPECT_EQ("int a = 5;\n" + "/*\n" + " * multi-line block comment\n" + " */\n" + "int oneTwoThree = 123;", + format("int a = 5;\n" + "/*\n" + " * multi-line block comment\n" + " */\n" + "int oneTwoThree=123;", + Alignment)); + + EXPECT_EQ("int a = 5;\n" + "//\n" + "// multi-line line comment\n" + "//\n" + "int oneTwoThree = 123;", + format("int a = 5;\n" + "//\n" + "// multi-line line comment\n" + "//\n" + "int oneTwoThree=123;", + Alignment)); + + /* Test across comments and newlines */ + EXPECT_EQ("int a = 5;\n" + "\n" + "/* block comment */\n" + "int oneTwoThree = 123;", + format("int a = 5;\n" + "\n" + "/* block comment */\n" + "int oneTwoThree=123;", + Alignment)); + + EXPECT_EQ("int a = 5;\n" + "\n" + "// line comment\n" + "int oneTwoThree = 123;", + format("int a = 5;\n" + "\n" + "// line comment\n" + "int oneTwoThree=123;", + Alignment)); +} + +TEST_F(FormatTest, AlignConsecutiveAssignmentsAcrossEmptyLinesAndComments) { + FormatStyle Alignment = getLLVMStyle(); + Alignment.AlignConsecutiveMacros = FormatStyle::ACS_Consecutive; + Alignment.AlignConsecutiveAssignments = + FormatStyle::ACS_AcrossEmptyLinesAndComments; + verifyFormat("int a = 5;\n" + "int oneTwoThree = 123;", + Alignment); + verifyFormat("int a = method();\n" + "int oneTwoThree = 133;", + Alignment); + verifyFormat("a &= 5;\n" + "bcd *= 5;\n" + "ghtyf += 5;\n" + "dvfvdb -= 5;\n" + "a /= 5;\n" + "vdsvsv %= 5;\n" + "sfdbddfbdfbb ^= 5;\n" + "dvsdsv |= 5;\n" + "int dsvvdvsdvvv = 123;", + Alignment); + verifyFormat("int i = 1, j = 10;\n" + "something = 2000;", + Alignment); + verifyFormat("something = 2000;\n" + "int i = 1, j = 10;\n", + Alignment); + verifyFormat("something = 2000;\n" + "another = 911;\n" + "int i = 1, j = 10;\n" + "oneMore = 1;\n" + "i = 2;", + Alignment); + verifyFormat("int a = 5;\n" + "int one = 1;\n" + "method();\n" + "int oneTwoThree = 123;\n" + "int oneTwo = 12;", + Alignment); + verifyFormat("int oneTwoThree = 123;\n" + "int oneTwo = 12;\n" + "method();\n", + Alignment); + verifyFormat("int oneTwoThree = 123; // comment\n" + "int oneTwo = 12; // comment", + Alignment); + + // Bug 25167 + /* Uncomment when fixed + verifyFormat("#if A\n" + "#else\n" + "int aaaaaaaa = 12;\n" + "#endif\n" + "#if B\n" + "#else\n" + "int a = 12;\n" + "#endif\n", + Alignment); + verifyFormat("enum foo {\n" + "#if A\n" + "#else\n" + " aaaaaaaa = 12;\n" + "#endif\n" + "#if B\n" + "#else\n" + " a = 12;\n" + "#endif\n" + "};\n", + Alignment); + */ + + Alignment.MaxEmptyLinesToKeep = 10; + /* Test alignment across empty lines */ + EXPECT_EQ("int a = 5;\n" + "\n" + "int oneTwoThree = 123;", + format("int a = 5;\n" + "\n" + "int oneTwoThree= 123;", + Alignment)); + EXPECT_EQ("int a = 5;\n" + "int one = 1;\n" + "\n" + "int oneTwoThree = 123;", + format("int a = 5;\n" + "int one = 1;\n" + "\n" + "int oneTwoThree = 123;", + Alignment)); + EXPECT_EQ("int a = 5;\n" + "int one = 1;\n" + "\n" + "int oneTwoThree = 123;\n" + "int oneTwo = 12;", + format("int a = 5;\n" + "int one = 1;\n" + "\n" + "int oneTwoThree = 123;\n" + "int oneTwo = 12;", + Alignment)); + + /* Test across comments */ + EXPECT_EQ("int a = 5;\n" + "/* block comment */\n" + "int oneTwoThree = 123;", + format("int a = 5;\n" + "/* block comment */\n" + "int oneTwoThree=123;", + Alignment)); + + EXPECT_EQ("int a = 5;\n" + "// line comment\n" + "int oneTwoThree = 123;", + format("int a = 5;\n" + "// line comment\n" + "int oneTwoThree=123;", + Alignment)); + + /* Test across comments and newlines */ + EXPECT_EQ("int a = 5;\n" + "\n" + "/* block comment */\n" + "int oneTwoThree = 123;", + format("int a = 5;\n" + "\n" + "/* block comment */\n" + "int oneTwoThree=123;", + Alignment)); + + EXPECT_EQ("int a = 5;\n" + "\n" + "// line comment\n" + "int oneTwoThree = 123;", + format("int a = 5;\n" + "\n" + "// line comment\n" + "int oneTwoThree=123;", + Alignment)); + + EXPECT_EQ("int a = 5;\n" + "//\n" + "// multi-line line comment\n" + "//\n" + "int oneTwoThree = 123;", + format("int a = 5;\n" + "//\n" + "// multi-line line comment\n" + "//\n" + "int oneTwoThree=123;", + Alignment)); + + EXPECT_EQ("int a = 5;\n" + "/*\n" + " * multi-line block comment\n" + " */\n" + "int oneTwoThree = 123;", + format("int a = 5;\n" + "/*\n" + " * multi-line block comment\n" + " */\n" + "int oneTwoThree=123;", + Alignment)); + + EXPECT_EQ("int a = 5;\n" + "\n" + "/* block comment */\n" + "\n" + "\n" + "\n" + "int oneTwoThree = 123;", + format("int a = 5;\n" + "\n" + "/* block comment */\n" + "\n" + "\n" + "\n" + "int oneTwoThree=123;", + Alignment)); + + EXPECT_EQ("int a = 5;\n" + "\n" + "// line comment\n" + "\n" + "\n" + "\n" + "int oneTwoThree = 123;", + format("int a = 5;\n" + "\n" + "// line comment\n" + "\n" + "\n" + "\n" + "int oneTwoThree=123;", + Alignment)); + + Alignment.AlignEscapedNewlines = FormatStyle::ENAS_DontAlign; + verifyFormat("#define A \\\n" + " int aaaa = 12; \\\n" + " int b = 23; \\\n" + " int ccc = 234; \\\n" + " int dddddddddd = 2345;", + Alignment); + Alignment.AlignEscapedNewlines = FormatStyle::ENAS_Left; + verifyFormat("#define A \\\n" + " int aaaa = 12; \\\n" + " int b = 23; \\\n" + " int ccc = 234; \\\n" + " int dddddddddd = 2345;", + Alignment); + Alignment.AlignEscapedNewlines = FormatStyle::ENAS_Right; + verifyFormat("#define A " + " \\\n" + " int aaaa = 12; " + " \\\n" + " int b = 23; " + " \\\n" + " int ccc = 234; " + " \\\n" + " int dddddddddd = 2345;", + Alignment); + verifyFormat("void SomeFunction(int parameter = 1, int i = 2, int j = 3, int " + "k = 4, int l = 5,\n" + " int m = 6) {\n" + " int j = 10;\n" + " otherThing = 1;\n" + "}", + Alignment); + verifyFormat("void SomeFunction(int parameter = 0) {\n" + " int i = 1;\n" + " int j = 2;\n" + " int big = 10000;\n" + "}", + Alignment); + verifyFormat("class C {\n" + "public:\n" + " int i = 1;\n" + " virtual void f() = 0;\n" + "};", + Alignment); + verifyFormat("int i = 1;\n" + "if (SomeType t = getSomething()) {\n" + "}\n" + "int j = 2;\n" + "int big = 10000;", + Alignment); + verifyFormat("int j = 7;\n" + "for (int k = 0; k < N; ++k) {\n" + "}\n" + "int j = 2;\n" + "int big = 10000;\n" + "}", + Alignment); + Alignment.BreakBeforeBinaryOperators = FormatStyle::BOS_All; + verifyFormat("int i = 1;\n" + "LooooooooooongType loooooooooooooooooooooongVariable\n" + " = someLooooooooooooooooongFunction();\n" + "int j = 2;", + Alignment); + Alignment.BreakBeforeBinaryOperators = FormatStyle::BOS_None; + verifyFormat("int i = 1;\n" + "LooooooooooongType loooooooooooooooooooooongVariable =\n" + " someLooooooooooooooooongFunction();\n" + "int j = 2;", + Alignment); + + verifyFormat("auto lambda = []() {\n" + " auto i = 0;\n" + " return 0;\n" + "};\n" + "int i = 0;\n" + "auto v = type{\n" + " i = 1, //\n" + " (i = 2), //\n" + " i = 3 //\n" + "};", + Alignment); + + verifyFormat( + "int i = 1;\n" + "SomeType a = SomeFunction(looooooooooooooooooooooongParameterA,\n" + " loooooooooooooooooooooongParameterB);\n" + "int j = 2;", + Alignment); + + verifyFormat("template \n" + "auto foo() {}\n", + Alignment); + verifyFormat("int a, b = 1;\n" + "int c = 2;\n" + "int dd = 3;\n", + Alignment); + verifyFormat("int aa = ((1 > 2) ? 3 : 4);\n" + "float b[1][] = {{3.f}};\n", + Alignment); + verifyFormat("for (int i = 0; i < 1; i++)\n" + " int x = 1;\n", + Alignment); + verifyFormat("for (i = 0; i < 1; i++)\n" + " x = 1;\n" + "y = 1;\n", + Alignment); + + Alignment.ReflowComments = true; + Alignment.ColumnLimit = 50; + EXPECT_EQ("int x = 0;\n" + "int yy = 1; /// specificlennospace\n" + "int zzz = 2;\n", + format("int x = 0;\n" + "int yy = 1; ///specificlennospace\n" + "int zzz = 2;\n", + Alignment)); } TEST_F(FormatTest, AlignConsecutiveAssignments) { FormatStyle Alignment = getLLVMStyle(); - Alignment.AlignConsecutiveMacros = true; - Alignment.AlignConsecutiveAssignments = false; + Alignment.AlignConsecutiveMacros = FormatStyle::ACS_Consecutive; + Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_None; verifyFormat("int a = 5;\n" "int oneTwoThree = 123;", Alignment); @@ -12574,7 +13328,7 @@ "int oneTwoThree = 123;", Alignment); - Alignment.AlignConsecutiveAssignments = true; + Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive; verifyFormat("int a = 5;\n" "int oneTwoThree = 123;", Alignment); @@ -12790,7 +13544,7 @@ TEST_F(FormatTest, AlignConsecutiveBitFields) { FormatStyle Alignment = getLLVMStyle(); - Alignment.AlignConsecutiveBitFields = true; + Alignment.AlignConsecutiveBitFields = FormatStyle::ACS_Consecutive; verifyFormat("int const a : 5;\n" "int oneTwoThree : 23;", Alignment); @@ -12800,7 +13554,7 @@ "int oneTwoThree : 23 = 0;", Alignment); - Alignment.AlignConsecutiveDeclarations = true; + Alignment.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive; verifyFormat("int const a : 5;\n" "int oneTwoThree : 23;", Alignment); @@ -12813,7 +13567,7 @@ "int oneTwoThree : 23 = 0;", Alignment); - Alignment.AlignConsecutiveAssignments = true; + Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive; verifyFormat("int const a : 5 = 1;\n" "int oneTwoThree : 23 = 0;", Alignment); @@ -12847,8 +13601,8 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) { FormatStyle Alignment = getLLVMStyle(); - Alignment.AlignConsecutiveMacros = true; - Alignment.AlignConsecutiveDeclarations = false; + Alignment.AlignConsecutiveMacros = FormatStyle::ACS_Consecutive; + Alignment.AlignConsecutiveDeclarations = FormatStyle::ACS_None; verifyFormat("float const a = 5;\n" "int oneTwoThree = 123;", Alignment); @@ -12856,7 +13610,7 @@ "float const oneTwoThree = 123;", Alignment); - Alignment.AlignConsecutiveDeclarations = true; + Alignment.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive; verifyFormat("float const a = 5;\n" "int oneTwoThree = 123;", Alignment); @@ -12953,7 +13707,7 @@ verifyFormat("int a(int x, void (*fp)(int y));\n" "double b();", Alignment); - Alignment.AlignConsecutiveAssignments = true; + Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive; // Ensure recursive alignment is broken by function braces, so that the // "a = 1" does not align with subsequent assignments inside the function // body. @@ -13016,7 +13770,7 @@ "int ll=10000;\n" "}", Alignment)); - Alignment.AlignConsecutiveAssignments = false; + Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_None; Alignment.AlignEscapedNewlines = FormatStyle::ENAS_DontAlign; verifyFormat("#define A \\\n" " int aaaa = 12; \\\n" @@ -13085,7 +13839,7 @@ "int j = 2;", Alignment); - Alignment.AlignConsecutiveAssignments = true; + Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive; verifyFormat("auto lambda = []() {\n" " auto ii = 0;\n" " float j = 0;\n" @@ -13099,7 +13853,7 @@ " i = 3 //\n" "};", Alignment); - Alignment.AlignConsecutiveAssignments = false; + Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_None; verifyFormat( "int i = 1;\n" @@ -13112,7 +13866,7 @@ // We expect declarations and assignments to align, as long as it doesn't // exceed the column limit, starting a new alignment sequence whenever it // happens. - Alignment.AlignConsecutiveAssignments = true; + Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive; Alignment.ColumnLimit = 30; verifyFormat("float ii = 1;\n" "unsigned j = 2;\n" @@ -13122,7 +13876,7 @@ "int myvar = 1;", Alignment); Alignment.ColumnLimit = 80; - Alignment.AlignConsecutiveAssignments = false; + Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_None; verifyFormat( "template 2) ? 3 : 4);\n" "float b[1][] = {{3.f}};\n", Alignment); - Alignment.AlignConsecutiveAssignments = true; + Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive; verifyFormat("float a, b = 1;\n" "int c = 2;\n" "int dd = 3;\n", @@ -13144,7 +13898,7 @@ verifyFormat("int aa = ((1 > 2) ? 3 : 4);\n" "float b[1][] = {{3.f}};\n", Alignment); - Alignment.AlignConsecutiveAssignments = false; + Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_None; Alignment.ColumnLimit = 30; Alignment.BinPackParameters = false; @@ -13175,7 +13929,7 @@ Alignment.PointerAlignment = FormatStyle::PAS_Right; // See llvm.org/PR35641 - Alignment.AlignConsecutiveDeclarations = true; + Alignment.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive; verifyFormat("int func() { //\n" " int b;\n" " unsigned c;\n" @@ -13184,7 +13938,7 @@ // See PR37175 FormatStyle Style = getMozillaStyle(); - Style.AlignConsecutiveDeclarations = true; + Style.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive; EXPECT_EQ("DECOR1 /**/ int8_t /**/ DECOR2 /**/\n" "foo(int a);", format("DECOR1 /**/ int8_t /**/ DECOR2 /**/ foo (int a);", Style)); @@ -14374,10 +15128,6 @@ FormatStyle Style = {}; Style.Language = FormatStyle::LK_Cpp; CHECK_PARSE_BOOL(AlignTrailingComments); - CHECK_PARSE_BOOL(AlignConsecutiveAssignments); - CHECK_PARSE_BOOL(AlignConsecutiveBitFields); - CHECK_PARSE_BOOL(AlignConsecutiveDeclarations); - CHECK_PARSE_BOOL(AlignConsecutiveMacros); CHECK_PARSE_BOOL(AllowAllArgumentsOnNextLine); CHECK_PARSE_BOOL(AllowAllConstructorInitializersOnNextLine); CHECK_PARSE_BOOL(AllowAllParametersOfDeclarationOnNextLine); @@ -14472,6 +15222,70 @@ CHECK_PARSE("ContinuationIndentWidth: 11", ContinuationIndentWidth, 11u); CHECK_PARSE("CommentPragmas: '// abc$'", CommentPragmas, "// abc$"); + Style.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive; + CHECK_PARSE("AlignConsecutiveAssignments: None", AlignConsecutiveAssignments, + FormatStyle::ACS_None); + CHECK_PARSE("AlignConsecutiveAssignments: Consecutive", + AlignConsecutiveAssignments, FormatStyle::ACS_Consecutive); + CHECK_PARSE("AlignConsecutiveAssignments: AcrossEmptyLines", + AlignConsecutiveAssignments, FormatStyle::ACS_AcrossEmptyLines); + CHECK_PARSE("AlignConsecutiveAssignments: AcrossEmptyLinesAndComments", + AlignConsecutiveAssignments, + FormatStyle::ACS_AcrossEmptyLinesAndComments); + // For backwards compability, false / true should still parse + CHECK_PARSE("AlignConsecutiveAssignments: false", AlignConsecutiveAssignments, + FormatStyle::ACS_None); + CHECK_PARSE("AlignConsecutiveAssignments: true", AlignConsecutiveAssignments, + FormatStyle::ACS_Consecutive); + + Style.AlignConsecutiveBitFields = FormatStyle::ACS_Consecutive; + CHECK_PARSE("AlignConsecutiveBitFields: None", AlignConsecutiveBitFields, + FormatStyle::ACS_None); + CHECK_PARSE("AlignConsecutiveBitFields: Consecutive", + AlignConsecutiveBitFields, FormatStyle::ACS_Consecutive); + CHECK_PARSE("AlignConsecutiveBitFields: AcrossEmptyLines", + AlignConsecutiveBitFields, FormatStyle::ACS_AcrossEmptyLines); + CHECK_PARSE("AlignConsecutiveBitFields: AcrossEmptyLinesAndComments", + AlignConsecutiveBitFields, + FormatStyle::ACS_AcrossEmptyLinesAndComments); + // For backwards compability, false / true should still parse + CHECK_PARSE("AlignConsecutiveBitFields: false", AlignConsecutiveBitFields, + FormatStyle::ACS_None); + CHECK_PARSE("AlignConsecutiveBitFields: true", AlignConsecutiveBitFields, + FormatStyle::ACS_Consecutive); + + Style.AlignConsecutiveMacros = FormatStyle::ACS_Consecutive; + CHECK_PARSE("AlignConsecutiveMacros: None", AlignConsecutiveMacros, + FormatStyle::ACS_None); + CHECK_PARSE("AlignConsecutiveMacros: Consecutive", AlignConsecutiveMacros, + FormatStyle::ACS_Consecutive); + CHECK_PARSE("AlignConsecutiveMacros: AcrossEmptyLines", + AlignConsecutiveMacros, FormatStyle::ACS_AcrossEmptyLines); + CHECK_PARSE("AlignConsecutiveMacros: AcrossEmptyLinesAndComments", + AlignConsecutiveMacros, + FormatStyle::ACS_AcrossEmptyLinesAndComments); + // For backwards compability, false / true should still parse + CHECK_PARSE("AlignConsecutiveMacros: false", AlignConsecutiveMacros, + FormatStyle::ACS_None); + CHECK_PARSE("AlignConsecutiveMacros: true", AlignConsecutiveMacros, + FormatStyle::ACS_Consecutive); + + Style.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive; + CHECK_PARSE("AlignConsecutiveDeclarations: None", + AlignConsecutiveDeclarations, FormatStyle::ACS_None); + CHECK_PARSE("AlignConsecutiveDeclarations: Consecutive", + AlignConsecutiveDeclarations, FormatStyle::ACS_Consecutive); + CHECK_PARSE("AlignConsecutiveDeclarations: AcrossEmptyLines", + AlignConsecutiveDeclarations, FormatStyle::ACS_AcrossEmptyLines); + CHECK_PARSE("AlignConsecutiveDeclarations: AcrossEmptyLinesAndComments", + AlignConsecutiveDeclarations, + FormatStyle::ACS_AcrossEmptyLinesAndComments); + // For backwards compability, false / true should still parse + CHECK_PARSE("AlignConsecutiveDeclarations: false", + AlignConsecutiveDeclarations, FormatStyle::ACS_None); + CHECK_PARSE("AlignConsecutiveDeclarations: true", + AlignConsecutiveDeclarations, FormatStyle::ACS_Consecutive); + Style.PointerAlignment = FormatStyle::PAS_Middle; CHECK_PARSE("PointerAlignment: Left", PointerAlignment, FormatStyle::PAS_Left); @@ -17400,7 +18214,7 @@ format("FOO(String-ized&Messy+But,: :\n" " Still=Intentional);", Style)); - Style.AlignConsecutiveAssignments = true; + Style.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive; EXPECT_EQ("FOO(String-ized=&Messy+But,: :\n" " Still=Intentional);", format("FOO(String-ized=&Messy+But,: :\n" @@ -17871,7 +18685,7 @@ EXPECT_EQ(Source, format(Source, Style)); - Style.AlignConsecutiveDeclarations = true; + Style.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive; EXPECT_EQ("void Foo::slot() {\n" " unsigned char MyChar = 'x';\n" " emit signal(MyChar);\n"