xref: /freebsd-src/contrib/llvm-project/clang/lib/Format/WhitespaceManager.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===--- WhitespaceManager.h - Format C++ code ------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric ///
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// WhitespaceManager class manages whitespace around tokens and their
110b57cec5SDimitry Andric /// replacements.
120b57cec5SDimitry Andric ///
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #ifndef LLVM_CLANG_LIB_FORMAT_WHITESPACEMANAGER_H
160b57cec5SDimitry Andric #define LLVM_CLANG_LIB_FORMAT_WHITESPACEMANAGER_H
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric #include "TokenAnnotator.h"
190b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h"
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric namespace clang {
220b57cec5SDimitry Andric namespace format {
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric /// Manages the whitespaces around tokens and their replacements.
250b57cec5SDimitry Andric ///
260b57cec5SDimitry Andric /// This includes special handling for certain constructs, e.g. the alignment of
270b57cec5SDimitry Andric /// trailing line comments.
280b57cec5SDimitry Andric ///
290b57cec5SDimitry Andric /// To guarantee correctness of alignment operations, the \c WhitespaceManager
300b57cec5SDimitry Andric /// must be informed about every token in the source file; for each token, there
310b57cec5SDimitry Andric /// must be exactly one call to either \c replaceWhitespace or
320b57cec5SDimitry Andric /// \c addUntouchableToken.
330b57cec5SDimitry Andric ///
340b57cec5SDimitry Andric /// There may be multiple calls to \c breakToken for a given token.
350b57cec5SDimitry Andric class WhitespaceManager {
360b57cec5SDimitry Andric public:
370b57cec5SDimitry Andric   WhitespaceManager(const SourceManager &SourceMgr, const FormatStyle &Style,
380b57cec5SDimitry Andric                     bool UseCRLF)
390b57cec5SDimitry Andric       : SourceMgr(SourceMgr), Style(Style), UseCRLF(UseCRLF) {}
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric   bool useCRLF() const { return UseCRLF; }
420b57cec5SDimitry Andric 
4304eeddc0SDimitry Andric   /// Infers whether the input is using CRLF.
4404eeddc0SDimitry Andric   static bool inputUsesCRLF(StringRef Text, bool DefaultToCRLF);
4504eeddc0SDimitry Andric 
460b57cec5SDimitry Andric   /// Replaces the whitespace in front of \p Tok. Only call once for
470b57cec5SDimitry Andric   /// each \c AnnotatedToken.
480b57cec5SDimitry Andric   ///
490b57cec5SDimitry Andric   /// \p StartOfTokenColumn is the column at which the token will start after
500b57cec5SDimitry Andric   /// this replacement. It is needed for determining how \p Spaces is turned
510b57cec5SDimitry Andric   /// into tabs and spaces for some format styles.
520b57cec5SDimitry Andric   void replaceWhitespace(FormatToken &Tok, unsigned Newlines, unsigned Spaces,
537a6dacacSDimitry Andric                          unsigned StartOfTokenColumn, bool IsAligned = false,
540b57cec5SDimitry Andric                          bool InPPDirective = false);
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric   /// Adds information about an unchangeable token's whitespace.
570b57cec5SDimitry Andric   ///
580b57cec5SDimitry Andric   /// Needs to be called for every token for which \c replaceWhitespace
590b57cec5SDimitry Andric   /// was not called.
600b57cec5SDimitry Andric   void addUntouchableToken(const FormatToken &Tok, bool InPPDirective);
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric   llvm::Error addReplacement(const tooling::Replacement &Replacement);
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric   /// Inserts or replaces whitespace in the middle of a token.
650b57cec5SDimitry Andric   ///
660b57cec5SDimitry Andric   /// Inserts \p PreviousPostfix, \p Newlines, \p Spaces and \p CurrentPrefix
670b57cec5SDimitry Andric   /// (in this order) at \p Offset inside \p Tok, replacing \p ReplaceChars
680b57cec5SDimitry Andric   /// characters.
690b57cec5SDimitry Andric   ///
700b57cec5SDimitry Andric   /// Note: \p Spaces can be negative to retain information about initial
710b57cec5SDimitry Andric   /// relative column offset between a line of a block comment and the start of
720b57cec5SDimitry Andric   /// the comment. This negative offset may be compensated by trailing comment
730b57cec5SDimitry Andric   /// alignment here. In all other cases negative \p Spaces will be truncated to
740b57cec5SDimitry Andric   /// 0.
750b57cec5SDimitry Andric   ///
760b57cec5SDimitry Andric   /// When \p InPPDirective is true, escaped newlines are inserted. \p Spaces is
770b57cec5SDimitry Andric   /// used to align backslashes correctly.
780b57cec5SDimitry Andric   void replaceWhitespaceInToken(const FormatToken &Tok, unsigned Offset,
790b57cec5SDimitry Andric                                 unsigned ReplaceChars,
800b57cec5SDimitry Andric                                 StringRef PreviousPostfix,
810b57cec5SDimitry Andric                                 StringRef CurrentPrefix, bool InPPDirective,
820b57cec5SDimitry Andric                                 unsigned Newlines, int Spaces);
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric   /// Returns all the \c Replacements created during formatting.
850b57cec5SDimitry Andric   const tooling::Replacements &generateReplacements();
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   /// Represents a change before a token, a break inside a token,
880b57cec5SDimitry Andric   /// or the layout of an unchanged token (or whitespace within).
890b57cec5SDimitry Andric   struct Change {
900b57cec5SDimitry Andric     /// Functor to sort changes in original source order.
910b57cec5SDimitry Andric     class IsBeforeInFile {
920b57cec5SDimitry Andric     public:
930b57cec5SDimitry Andric       IsBeforeInFile(const SourceManager &SourceMgr) : SourceMgr(SourceMgr) {}
940b57cec5SDimitry Andric       bool operator()(const Change &C1, const Change &C2) const;
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric     private:
970b57cec5SDimitry Andric       const SourceManager &SourceMgr;
980b57cec5SDimitry Andric     };
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric     /// Creates a \c Change.
1010b57cec5SDimitry Andric     ///
1020b57cec5SDimitry Andric     /// The generated \c Change will replace the characters at
1030b57cec5SDimitry Andric     /// \p OriginalWhitespaceRange with a concatenation of
1040b57cec5SDimitry Andric     /// \p PreviousLinePostfix, \p NewlinesBefore line breaks, \p Spaces spaces
1050b57cec5SDimitry Andric     /// and \p CurrentLinePrefix.
1060b57cec5SDimitry Andric     ///
1070b57cec5SDimitry Andric     /// \p StartOfTokenColumn and \p InPPDirective will be used to lay out
1080b57cec5SDimitry Andric     /// trailing comments and escaped newlines.
1090b57cec5SDimitry Andric     Change(const FormatToken &Tok, bool CreateReplacement,
1100b57cec5SDimitry Andric            SourceRange OriginalWhitespaceRange, int Spaces,
1110b57cec5SDimitry Andric            unsigned StartOfTokenColumn, unsigned NewlinesBefore,
1120b57cec5SDimitry Andric            StringRef PreviousLinePostfix, StringRef CurrentLinePrefix,
1135ffd83dbSDimitry Andric            bool IsAligned, bool ContinuesPPDirective, bool IsInsideToken);
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric     // The kind of the token whose whitespace this change replaces, or in which
1160b57cec5SDimitry Andric     // this change inserts whitespace.
1170b57cec5SDimitry Andric     // FIXME: Currently this is not set correctly for breaks inside comments, as
1180b57cec5SDimitry Andric     // the \c BreakableToken is still doing its own alignment.
1190b57cec5SDimitry Andric     const FormatToken *Tok;
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric     bool CreateReplacement;
1220b57cec5SDimitry Andric     // Changes might be in the middle of a token, so we cannot just keep the
1230b57cec5SDimitry Andric     // FormatToken around to query its information.
1240b57cec5SDimitry Andric     SourceRange OriginalWhitespaceRange;
1250b57cec5SDimitry Andric     unsigned StartOfTokenColumn;
1260b57cec5SDimitry Andric     unsigned NewlinesBefore;
1270b57cec5SDimitry Andric     std::string PreviousLinePostfix;
1280b57cec5SDimitry Andric     std::string CurrentLinePrefix;
1295ffd83dbSDimitry Andric     bool IsAligned;
1300b57cec5SDimitry Andric     bool ContinuesPPDirective;
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric     // The number of spaces in front of the token or broken part of the token.
1330b57cec5SDimitry Andric     // This will be adapted when aligning tokens.
1340b57cec5SDimitry Andric     // Can be negative to retain information about the initial relative offset
1350b57cec5SDimitry Andric     // of the lines in a block comment. This is used when aligning trailing
1360b57cec5SDimitry Andric     // comments. Uncompensated negative offset is truncated to 0.
1370b57cec5SDimitry Andric     int Spaces;
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric     // If this change is inside of a token but not at the start of the token or
1400b57cec5SDimitry Andric     // directly after a newline.
1410b57cec5SDimitry Andric     bool IsInsideToken;
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric     // \c IsTrailingComment, \c TokenLength, \c PreviousEndOfTokenColumn and
1440b57cec5SDimitry Andric     // \c EscapedNewlineColumn will be calculated in
1450b57cec5SDimitry Andric     // \c calculateLineBreakInformation.
1460b57cec5SDimitry Andric     bool IsTrailingComment;
1470b57cec5SDimitry Andric     unsigned TokenLength;
1480b57cec5SDimitry Andric     unsigned PreviousEndOfTokenColumn;
1490b57cec5SDimitry Andric     unsigned EscapedNewlineColumn;
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric     // These fields are used to retain correct relative line indentation in a
1520b57cec5SDimitry Andric     // block comment when aligning trailing comments.
1530b57cec5SDimitry Andric     //
1540b57cec5SDimitry Andric     // If this Change represents a continuation of a block comment,
1550b57cec5SDimitry Andric     // \c StartOfBlockComment is pointer to the first Change in the block
1560b57cec5SDimitry Andric     // comment. \c IndentationOffset is a relative column offset to this
1570b57cec5SDimitry Andric     // change, so that the correct column can be reconstructed at the end of
1580b57cec5SDimitry Andric     // the alignment process.
1590b57cec5SDimitry Andric     const Change *StartOfBlockComment;
1600b57cec5SDimitry Andric     int IndentationOffset;
1610b57cec5SDimitry Andric 
1625ffd83dbSDimitry Andric     // Depth of conditionals. Computed from tracking fake parenthesis, except
1635ffd83dbSDimitry Andric     // it does not increase the indent for "chained" conditionals.
1645ffd83dbSDimitry Andric     int ConditionalsLevel;
1655ffd83dbSDimitry Andric 
1665ffd83dbSDimitry Andric     // A combination of indent, nesting and conditionals levels, which are used
1675ffd83dbSDimitry Andric     // in tandem to compute lexical scope, for the purposes of deciding
1680b57cec5SDimitry Andric     // when to stop consecutive alignment runs.
1695ffd83dbSDimitry Andric     std::tuple<unsigned, unsigned, unsigned> indentAndNestingLevel() const {
1705ffd83dbSDimitry Andric       return std::make_tuple(Tok->IndentLevel, Tok->NestingLevel,
1715ffd83dbSDimitry Andric                              ConditionalsLevel);
1720b57cec5SDimitry Andric     }
1730b57cec5SDimitry Andric   };
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric private:
176fe6060f1SDimitry Andric   struct CellDescription {
177fe6060f1SDimitry Andric     unsigned Index = 0;
178fe6060f1SDimitry Andric     unsigned Cell = 0;
179fe6060f1SDimitry Andric     unsigned EndIndex = 0;
180fe6060f1SDimitry Andric     bool HasSplit = false;
181fe6060f1SDimitry Andric     CellDescription *NextColumnElement = nullptr;
182fe6060f1SDimitry Andric 
183fe6060f1SDimitry Andric     constexpr bool operator==(const CellDescription &Other) const {
184fe6060f1SDimitry Andric       return Index == Other.Index && Cell == Other.Cell &&
185fe6060f1SDimitry Andric              EndIndex == Other.EndIndex;
186fe6060f1SDimitry Andric     }
187fe6060f1SDimitry Andric     constexpr bool operator!=(const CellDescription &Other) const {
188fe6060f1SDimitry Andric       return !(*this == Other);
189fe6060f1SDimitry Andric     }
190fe6060f1SDimitry Andric   };
191fe6060f1SDimitry Andric 
192fe6060f1SDimitry Andric   struct CellDescriptions {
193fe6060f1SDimitry Andric     SmallVector<CellDescription> Cells;
19481ad6265SDimitry Andric     SmallVector<unsigned> CellCounts;
195fe6060f1SDimitry Andric     unsigned InitialSpaces = 0;
19681ad6265SDimitry Andric 
197bdd1243dSDimitry Andric     // Determine if every row in the array
19881ad6265SDimitry Andric     // has the same number of columns.
19981ad6265SDimitry Andric     bool isRectangular() const {
2005f757f3fSDimitry Andric       if (CellCounts.size() < 2)
20181ad6265SDimitry Andric         return false;
20281ad6265SDimitry Andric 
20381ad6265SDimitry Andric       for (auto NumberOfColumns : CellCounts)
20481ad6265SDimitry Andric         if (NumberOfColumns != CellCounts[0])
20581ad6265SDimitry Andric           return false;
20681ad6265SDimitry Andric       return true;
20781ad6265SDimitry Andric     }
208fe6060f1SDimitry Andric   };
209fe6060f1SDimitry Andric 
2100b57cec5SDimitry Andric   /// Calculate \c IsTrailingComment, \c TokenLength for the last tokens
2110b57cec5SDimitry Andric   /// or token parts in a line and \c PreviousEndOfTokenColumn and
2120b57cec5SDimitry Andric   /// \c EscapedNewlineColumn for the first tokens or token parts in a line.
2130b57cec5SDimitry Andric   void calculateLineBreakInformation();
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric   /// \brief Align consecutive C/C++ preprocessor macros over all \c Changes.
2160b57cec5SDimitry Andric   void alignConsecutiveMacros();
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric   /// Align consecutive assignments over all \c Changes.
2190b57cec5SDimitry Andric   void alignConsecutiveAssignments();
2200b57cec5SDimitry Andric 
2215ffd83dbSDimitry Andric   /// Align consecutive bitfields over all \c Changes.
2225ffd83dbSDimitry Andric   void alignConsecutiveBitFields();
2235ffd83dbSDimitry Andric 
224*0fca6ea1SDimitry Andric   /// Align consecutive colon. For bitfields, TableGen DAGArgs and defintions.
225*0fca6ea1SDimitry Andric   void
226*0fca6ea1SDimitry Andric   alignConsecutiveColons(const FormatStyle::AlignConsecutiveStyle &AlignStyle,
227*0fca6ea1SDimitry Andric                          TokenType Type);
228*0fca6ea1SDimitry Andric 
2290b57cec5SDimitry Andric   /// Align consecutive declarations over all \c Changes.
2300b57cec5SDimitry Andric   void alignConsecutiveDeclarations();
2310b57cec5SDimitry Andric 
2325ffd83dbSDimitry Andric   /// Align consecutive declarations over all \c Changes.
2335ffd83dbSDimitry Andric   void alignChainedConditionals();
2345ffd83dbSDimitry Andric 
23506c3fb27SDimitry Andric   /// Align consecutive short case statements over all \c Changes.
236*0fca6ea1SDimitry Andric   void alignConsecutiveShortCaseStatements(bool IsExpr);
237*0fca6ea1SDimitry Andric 
238*0fca6ea1SDimitry Andric   /// Align consecutive TableGen DAGArg colon over all \c Changes.
239*0fca6ea1SDimitry Andric   void alignConsecutiveTableGenBreakingDAGArgColons();
240*0fca6ea1SDimitry Andric 
241*0fca6ea1SDimitry Andric   /// Align consecutive TableGen cond operator colon over all \c Changes.
242*0fca6ea1SDimitry Andric   void alignConsecutiveTableGenCondOperatorColons();
243*0fca6ea1SDimitry Andric 
244*0fca6ea1SDimitry Andric   /// Align consecutive TableGen definitions over all \c Changes.
245*0fca6ea1SDimitry Andric   void alignConsecutiveTableGenDefinitions();
24606c3fb27SDimitry Andric 
2470b57cec5SDimitry Andric   /// Align trailing comments over all \c Changes.
2480b57cec5SDimitry Andric   void alignTrailingComments();
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric   /// Align trailing comments from change \p Start to change \p End at
2510b57cec5SDimitry Andric   /// the specified \p Column.
2520b57cec5SDimitry Andric   void alignTrailingComments(unsigned Start, unsigned End, unsigned Column);
2530b57cec5SDimitry Andric 
2540b57cec5SDimitry Andric   /// Align escaped newlines over all \c Changes.
2550b57cec5SDimitry Andric   void alignEscapedNewlines();
2560b57cec5SDimitry Andric 
2570b57cec5SDimitry Andric   /// Align escaped newlines from change \p Start to change \p End at
2580b57cec5SDimitry Andric   /// the specified \p Column.
2590b57cec5SDimitry Andric   void alignEscapedNewlines(unsigned Start, unsigned End, unsigned Column);
2600b57cec5SDimitry Andric 
261fe6060f1SDimitry Andric   /// Align Array Initializers over all \c Changes.
262fe6060f1SDimitry Andric   void alignArrayInitializers();
263fe6060f1SDimitry Andric 
264fe6060f1SDimitry Andric   /// Align Array Initializers from change \p Start to change \p End at
265fe6060f1SDimitry Andric   /// the specified \p Column.
266fe6060f1SDimitry Andric   void alignArrayInitializers(unsigned Start, unsigned End);
267fe6060f1SDimitry Andric 
268fe6060f1SDimitry Andric   /// Align Array Initializers being careful to right justify the columns
269fe6060f1SDimitry Andric   /// as described by \p CellDescs.
270fe6060f1SDimitry Andric   void alignArrayInitializersRightJustified(CellDescriptions &&CellDescs);
271fe6060f1SDimitry Andric 
27204eeddc0SDimitry Andric   /// Align Array Initializers being careful to left justify the columns
273fe6060f1SDimitry Andric   /// as described by \p CellDescs.
274fe6060f1SDimitry Andric   void alignArrayInitializersLeftJustified(CellDescriptions &&CellDescs);
275fe6060f1SDimitry Andric 
276fe6060f1SDimitry Andric   /// Calculate the cell width between two indexes.
277fe6060f1SDimitry Andric   unsigned calculateCellWidth(unsigned Start, unsigned End,
278fe6060f1SDimitry Andric                               bool WithSpaces = false) const;
279fe6060f1SDimitry Andric 
280fe6060f1SDimitry Andric   /// Get a set of fully specified CellDescriptions between \p Start and
281fe6060f1SDimitry Andric   /// \p End of the change list.
282fe6060f1SDimitry Andric   CellDescriptions getCells(unsigned Start, unsigned End);
283fe6060f1SDimitry Andric 
284fe6060f1SDimitry Andric   /// Does this \p Cell contain a split element?
285fe6060f1SDimitry Andric   static bool isSplitCell(const CellDescription &Cell);
286fe6060f1SDimitry Andric 
287349cc55cSDimitry Andric   /// Get the width of the preceding cells from \p Start to \p End.
288fe6060f1SDimitry Andric   template <typename I>
289fe6060f1SDimitry Andric   auto getNetWidth(const I &Start, const I &End, unsigned InitialSpaces) const {
290fe6060f1SDimitry Andric     auto NetWidth = InitialSpaces;
291fe6060f1SDimitry Andric     for (auto PrevIter = Start; PrevIter != End; ++PrevIter) {
292fe6060f1SDimitry Andric       // If we broke the line the initial spaces are already
293fe6060f1SDimitry Andric       // accounted for.
294297eecfbSDimitry Andric       assert(PrevIter->Index < Changes.size());
295fe6060f1SDimitry Andric       if (Changes[PrevIter->Index].NewlinesBefore > 0)
296fe6060f1SDimitry Andric         NetWidth = 0;
297fe6060f1SDimitry Andric       NetWidth +=
298fe6060f1SDimitry Andric           calculateCellWidth(PrevIter->Index, PrevIter->EndIndex, true) + 1;
299fe6060f1SDimitry Andric     }
300fe6060f1SDimitry Andric     return NetWidth;
301fe6060f1SDimitry Andric   }
302fe6060f1SDimitry Andric 
303fe6060f1SDimitry Andric   /// Get the maximum width of a cell in a sequence of columns.
304fe6060f1SDimitry Andric   template <typename I>
305fe6060f1SDimitry Andric   unsigned getMaximumCellWidth(I CellIter, unsigned NetWidth) const {
306fe6060f1SDimitry Andric     unsigned CellWidth =
307fe6060f1SDimitry Andric         calculateCellWidth(CellIter->Index, CellIter->EndIndex, true);
308fe6060f1SDimitry Andric     if (Changes[CellIter->Index].NewlinesBefore == 0)
309fe6060f1SDimitry Andric       CellWidth += NetWidth;
31006c3fb27SDimitry Andric     for (const auto *Next = CellIter->NextColumnElement; Next;
311fe6060f1SDimitry Andric          Next = Next->NextColumnElement) {
312fe6060f1SDimitry Andric       auto ThisWidth = calculateCellWidth(Next->Index, Next->EndIndex, true);
313fe6060f1SDimitry Andric       if (Changes[Next->Index].NewlinesBefore == 0)
314fe6060f1SDimitry Andric         ThisWidth += NetWidth;
315fe6060f1SDimitry Andric       CellWidth = std::max(CellWidth, ThisWidth);
316fe6060f1SDimitry Andric     }
317fe6060f1SDimitry Andric     return CellWidth;
318fe6060f1SDimitry Andric   }
319fe6060f1SDimitry Andric 
320fe6060f1SDimitry Andric   /// Get The maximum width of all columns to a given cell.
321fe6060f1SDimitry Andric   template <typename I>
322fe6060f1SDimitry Andric   unsigned getMaximumNetWidth(const I &CellStart, const I &CellStop,
32381ad6265SDimitry Andric                               unsigned InitialSpaces, unsigned CellCount,
32481ad6265SDimitry Andric                               unsigned MaxRowCount) const {
325fe6060f1SDimitry Andric     auto MaxNetWidth = getNetWidth(CellStart, CellStop, InitialSpaces);
326fe6060f1SDimitry Andric     auto RowCount = 1U;
327fe6060f1SDimitry Andric     auto Offset = std::distance(CellStart, CellStop);
32806c3fb27SDimitry Andric     for (const auto *Next = CellStop->NextColumnElement; Next;
329fe6060f1SDimitry Andric          Next = Next->NextColumnElement) {
3305c16e71dSDimitry Andric       if (RowCount >= MaxRowCount)
33181ad6265SDimitry Andric         break;
332fe6060f1SDimitry Andric       auto Start = (CellStart + RowCount * CellCount);
333fe6060f1SDimitry Andric       auto End = Start + Offset;
334fe6060f1SDimitry Andric       MaxNetWidth =
335fe6060f1SDimitry Andric           std::max(MaxNetWidth, getNetWidth(Start, End, InitialSpaces));
336fe6060f1SDimitry Andric       ++RowCount;
337fe6060f1SDimitry Andric     }
338fe6060f1SDimitry Andric     return MaxNetWidth;
339fe6060f1SDimitry Andric   }
340fe6060f1SDimitry Andric 
341fe6060f1SDimitry Andric   /// Align a split cell with a newline to the first element in the cell.
342fe6060f1SDimitry Andric   void alignToStartOfCell(unsigned Start, unsigned End);
343fe6060f1SDimitry Andric 
344fe6060f1SDimitry Andric   /// Link the Cell pointers in the list of Cells.
345fe6060f1SDimitry Andric   static CellDescriptions linkCells(CellDescriptions &&CellDesc);
346fe6060f1SDimitry Andric 
3470b57cec5SDimitry Andric   /// Fill \c Replaces with the replacements for all effective changes.
3480b57cec5SDimitry Andric   void generateChanges();
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric   /// Stores \p Text as the replacement for the whitespace in \p Range.
3510b57cec5SDimitry Andric   void storeReplacement(SourceRange Range, StringRef Text);
3520b57cec5SDimitry Andric   void appendNewlineText(std::string &Text, unsigned Newlines);
3530b57cec5SDimitry Andric   void appendEscapedNewlineText(std::string &Text, unsigned Newlines,
3540b57cec5SDimitry Andric                                 unsigned PreviousEndOfTokenColumn,
3550b57cec5SDimitry Andric                                 unsigned EscapedNewlineColumn);
3560b57cec5SDimitry Andric   void appendIndentText(std::string &Text, unsigned IndentLevel,
3575ffd83dbSDimitry Andric                         unsigned Spaces, unsigned WhitespaceStartColumn,
3585ffd83dbSDimitry Andric                         bool IsAligned);
3595ffd83dbSDimitry Andric   unsigned appendTabIndent(std::string &Text, unsigned Spaces,
3605ffd83dbSDimitry Andric                            unsigned Indentation);
3610b57cec5SDimitry Andric 
3620b57cec5SDimitry Andric   SmallVector<Change, 16> Changes;
3630b57cec5SDimitry Andric   const SourceManager &SourceMgr;
3640b57cec5SDimitry Andric   tooling::Replacements Replaces;
3650b57cec5SDimitry Andric   const FormatStyle &Style;
3660b57cec5SDimitry Andric   bool UseCRLF;
3670b57cec5SDimitry Andric };
3680b57cec5SDimitry Andric 
3690b57cec5SDimitry Andric } // namespace format
3700b57cec5SDimitry Andric } // namespace clang
3710b57cec5SDimitry Andric 
3720b57cec5SDimitry Andric #endif
373