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