1f4a2713aSLionel Sambuc //===--- WhitespaceManager.h - Format C++ code ------------------*- C++ -*-===// 2f4a2713aSLionel Sambuc // 3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure 4f4a2713aSLionel Sambuc // 5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source 6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details. 7f4a2713aSLionel Sambuc // 8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 9f4a2713aSLionel Sambuc /// 10f4a2713aSLionel Sambuc /// \file 11f4a2713aSLionel Sambuc /// \brief WhitespaceManager class manages whitespace around tokens and their 12f4a2713aSLionel Sambuc /// replacements. 13f4a2713aSLionel Sambuc /// 14f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 15f4a2713aSLionel Sambuc 16*0a6a1f1dSLionel Sambuc #ifndef LLVM_CLANG_LIB_FORMAT_WHITESPACEMANAGER_H 17*0a6a1f1dSLionel Sambuc #define LLVM_CLANG_LIB_FORMAT_WHITESPACEMANAGER_H 18f4a2713aSLionel Sambuc 19f4a2713aSLionel Sambuc #include "TokenAnnotator.h" 20f4a2713aSLionel Sambuc #include "clang/Basic/SourceManager.h" 21f4a2713aSLionel Sambuc #include "clang/Format/Format.h" 22f4a2713aSLionel Sambuc #include <string> 23f4a2713aSLionel Sambuc 24f4a2713aSLionel Sambuc namespace clang { 25f4a2713aSLionel Sambuc namespace format { 26f4a2713aSLionel Sambuc 27f4a2713aSLionel Sambuc /// \brief Manages the whitespaces around tokens and their replacements. 28f4a2713aSLionel Sambuc /// 29f4a2713aSLionel Sambuc /// This includes special handling for certain constructs, e.g. the alignment of 30f4a2713aSLionel Sambuc /// trailing line comments. 31f4a2713aSLionel Sambuc /// 32f4a2713aSLionel Sambuc /// To guarantee correctness of alignment operations, the \c WhitespaceManager 33f4a2713aSLionel Sambuc /// must be informed about every token in the source file; for each token, there 34f4a2713aSLionel Sambuc /// must be exactly one call to either \c replaceWhitespace or 35f4a2713aSLionel Sambuc /// \c addUntouchableToken. 36f4a2713aSLionel Sambuc /// 37f4a2713aSLionel Sambuc /// There may be multiple calls to \c breakToken for a given token. 38f4a2713aSLionel Sambuc class WhitespaceManager { 39f4a2713aSLionel Sambuc public: WhitespaceManager(SourceManager & SourceMgr,const FormatStyle & Style,bool UseCRLF)40f4a2713aSLionel Sambuc WhitespaceManager(SourceManager &SourceMgr, const FormatStyle &Style, 41f4a2713aSLionel Sambuc bool UseCRLF) 42f4a2713aSLionel Sambuc : SourceMgr(SourceMgr), Style(Style), UseCRLF(UseCRLF) {} 43f4a2713aSLionel Sambuc 44f4a2713aSLionel Sambuc /// \brief Prepares the \c WhitespaceManager for another run. 45f4a2713aSLionel Sambuc void reset(); 46f4a2713aSLionel Sambuc 47f4a2713aSLionel Sambuc /// \brief Replaces the whitespace in front of \p Tok. Only call once for 48f4a2713aSLionel Sambuc /// each \c AnnotatedToken. 49f4a2713aSLionel Sambuc void replaceWhitespace(FormatToken &Tok, unsigned Newlines, 50f4a2713aSLionel Sambuc unsigned IndentLevel, unsigned Spaces, 51f4a2713aSLionel Sambuc unsigned StartOfTokenColumn, 52f4a2713aSLionel Sambuc bool InPPDirective = false); 53f4a2713aSLionel Sambuc 54*0a6a1f1dSLionel Sambuc /// \brief Adds information about an unchangeable token's whitespace. 55f4a2713aSLionel Sambuc /// 56f4a2713aSLionel Sambuc /// Needs to be called for every token for which \c replaceWhitespace 57f4a2713aSLionel Sambuc /// was not called. 58f4a2713aSLionel Sambuc void addUntouchableToken(const FormatToken &Tok, bool InPPDirective); 59f4a2713aSLionel Sambuc 60f4a2713aSLionel Sambuc /// \brief Inserts or replaces whitespace in the middle of a token. 61f4a2713aSLionel Sambuc /// 62f4a2713aSLionel Sambuc /// Inserts \p PreviousPostfix, \p Newlines, \p Spaces and \p CurrentPrefix 63f4a2713aSLionel Sambuc /// (in this order) at \p Offset inside \p Tok, replacing \p ReplaceChars 64f4a2713aSLionel Sambuc /// characters. 65f4a2713aSLionel Sambuc /// 66*0a6a1f1dSLionel Sambuc /// Note: \p Spaces can be negative to retain information about initial 67*0a6a1f1dSLionel Sambuc /// relative column offset between a line of a block comment and the start of 68*0a6a1f1dSLionel Sambuc /// the comment. This negative offset may be compensated by trailing comment 69*0a6a1f1dSLionel Sambuc /// alignment here. In all other cases negative \p Spaces will be truncated to 70*0a6a1f1dSLionel Sambuc /// 0. 71*0a6a1f1dSLionel Sambuc /// 72f4a2713aSLionel Sambuc /// When \p InPPDirective is true, escaped newlines are inserted. \p Spaces is 73f4a2713aSLionel Sambuc /// used to align backslashes correctly. 74f4a2713aSLionel Sambuc void replaceWhitespaceInToken(const FormatToken &Tok, unsigned Offset, 75f4a2713aSLionel Sambuc unsigned ReplaceChars, 76f4a2713aSLionel Sambuc StringRef PreviousPostfix, 77f4a2713aSLionel Sambuc StringRef CurrentPrefix, bool InPPDirective, 78f4a2713aSLionel Sambuc unsigned Newlines, unsigned IndentLevel, 79*0a6a1f1dSLionel Sambuc int Spaces); 80f4a2713aSLionel Sambuc 81f4a2713aSLionel Sambuc /// \brief Returns all the \c Replacements created during formatting. 82f4a2713aSLionel Sambuc const tooling::Replacements &generateReplacements(); 83f4a2713aSLionel Sambuc 84f4a2713aSLionel Sambuc private: 85f4a2713aSLionel Sambuc /// \brief Represents a change before a token, a break inside a token, 86f4a2713aSLionel Sambuc /// or the layout of an unchanged token (or whitespace within). 87f4a2713aSLionel Sambuc struct Change { 88f4a2713aSLionel Sambuc /// \brief Functor to sort changes in original source order. 89f4a2713aSLionel Sambuc class IsBeforeInFile { 90f4a2713aSLionel Sambuc public: IsBeforeInFileChange91f4a2713aSLionel Sambuc IsBeforeInFile(const SourceManager &SourceMgr) : SourceMgr(SourceMgr) {} 92f4a2713aSLionel Sambuc bool operator()(const Change &C1, const Change &C2) const; 93f4a2713aSLionel Sambuc 94f4a2713aSLionel Sambuc private: 95f4a2713aSLionel Sambuc const SourceManager &SourceMgr; 96f4a2713aSLionel Sambuc }; 97f4a2713aSLionel Sambuc ChangeChange98f4a2713aSLionel Sambuc Change() {} 99f4a2713aSLionel Sambuc 100f4a2713aSLionel Sambuc /// \brief Creates a \c Change. 101f4a2713aSLionel Sambuc /// 102f4a2713aSLionel Sambuc /// The generated \c Change will replace the characters at 103f4a2713aSLionel Sambuc /// \p OriginalWhitespaceRange with a concatenation of 104f4a2713aSLionel Sambuc /// \p PreviousLinePostfix, \p NewlinesBefore line breaks, \p Spaces spaces 105f4a2713aSLionel Sambuc /// and \p CurrentLinePrefix. 106f4a2713aSLionel Sambuc /// 107f4a2713aSLionel Sambuc /// \p StartOfTokenColumn and \p InPPDirective will be used to lay out 108f4a2713aSLionel Sambuc /// trailing comments and escaped newlines. 109f4a2713aSLionel Sambuc Change(bool CreateReplacement, const SourceRange &OriginalWhitespaceRange, 110*0a6a1f1dSLionel Sambuc unsigned IndentLevel, int Spaces, unsigned StartOfTokenColumn, 111f4a2713aSLionel Sambuc unsigned NewlinesBefore, StringRef PreviousLinePostfix, 112f4a2713aSLionel Sambuc StringRef CurrentLinePrefix, tok::TokenKind Kind, 113f4a2713aSLionel Sambuc bool ContinuesPPDirective); 114f4a2713aSLionel Sambuc 115f4a2713aSLionel Sambuc bool CreateReplacement; 116f4a2713aSLionel Sambuc // Changes might be in the middle of a token, so we cannot just keep the 117f4a2713aSLionel Sambuc // FormatToken around to query its information. 118f4a2713aSLionel Sambuc SourceRange OriginalWhitespaceRange; 119f4a2713aSLionel Sambuc unsigned StartOfTokenColumn; 120f4a2713aSLionel Sambuc unsigned NewlinesBefore; 121f4a2713aSLionel Sambuc std::string PreviousLinePostfix; 122f4a2713aSLionel Sambuc std::string CurrentLinePrefix; 123f4a2713aSLionel Sambuc // The kind of the token whose whitespace this change replaces, or in which 124f4a2713aSLionel Sambuc // this change inserts whitespace. 125f4a2713aSLionel Sambuc // FIXME: Currently this is not set correctly for breaks inside comments, as 126f4a2713aSLionel Sambuc // the \c BreakableToken is still doing its own alignment. 127f4a2713aSLionel Sambuc tok::TokenKind Kind; 128f4a2713aSLionel Sambuc bool ContinuesPPDirective; 129f4a2713aSLionel Sambuc 130f4a2713aSLionel Sambuc // The number of nested blocks the token is in. This is used to add tabs 131f4a2713aSLionel Sambuc // only for the indentation, and not for alignment, when 132f4a2713aSLionel Sambuc // UseTab = US_ForIndentation. 133f4a2713aSLionel Sambuc unsigned IndentLevel; 134f4a2713aSLionel Sambuc 135f4a2713aSLionel Sambuc // The number of spaces in front of the token or broken part of the token. 136f4a2713aSLionel Sambuc // This will be adapted when aligning tokens. 137*0a6a1f1dSLionel Sambuc // Can be negative to retain information about the initial relative offset 138*0a6a1f1dSLionel Sambuc // of the lines in a block comment. This is used when aligning trailing 139*0a6a1f1dSLionel Sambuc // comments. Uncompensated negative offset is truncated to 0. 140*0a6a1f1dSLionel Sambuc int Spaces; 141f4a2713aSLionel Sambuc 142f4a2713aSLionel Sambuc // \c IsTrailingComment, \c TokenLength, \c PreviousEndOfTokenColumn and 143f4a2713aSLionel Sambuc // \c EscapedNewlineColumn will be calculated in 144f4a2713aSLionel Sambuc // \c calculateLineBreakInformation. 145f4a2713aSLionel Sambuc bool IsTrailingComment; 146f4a2713aSLionel Sambuc unsigned TokenLength; 147f4a2713aSLionel Sambuc unsigned PreviousEndOfTokenColumn; 148f4a2713aSLionel Sambuc unsigned EscapedNewlineColumn; 149*0a6a1f1dSLionel Sambuc 150*0a6a1f1dSLionel Sambuc // These fields are used to retain correct relative line indentation in a 151*0a6a1f1dSLionel Sambuc // block comment when aligning trailing comments. 152*0a6a1f1dSLionel Sambuc // 153*0a6a1f1dSLionel Sambuc // If this Change represents a continuation of a block comment, 154*0a6a1f1dSLionel Sambuc // \c StartOfBlockComment is pointer to the first Change in the block 155*0a6a1f1dSLionel Sambuc // comment. \c IndentationOffset is a relative column offset to this 156*0a6a1f1dSLionel Sambuc // change, so that the correct column can be reconstructed at the end of 157*0a6a1f1dSLionel Sambuc // the alignment process. 158*0a6a1f1dSLionel Sambuc const Change *StartOfBlockComment; 159*0a6a1f1dSLionel Sambuc int IndentationOffset; 160f4a2713aSLionel Sambuc }; 161f4a2713aSLionel Sambuc 162f4a2713aSLionel Sambuc /// \brief Calculate \c IsTrailingComment, \c TokenLength for the last tokens 163f4a2713aSLionel Sambuc /// or token parts in a line and \c PreviousEndOfTokenColumn and 164f4a2713aSLionel Sambuc /// \c EscapedNewlineColumn for the first tokens or token parts in a line. 165f4a2713aSLionel Sambuc void calculateLineBreakInformation(); 166f4a2713aSLionel Sambuc 167f4a2713aSLionel Sambuc /// \brief Align trailing comments over all \c Changes. 168f4a2713aSLionel Sambuc void alignTrailingComments(); 169f4a2713aSLionel Sambuc 170f4a2713aSLionel Sambuc /// \brief Align trailing comments from change \p Start to change \p End at 171f4a2713aSLionel Sambuc /// the specified \p Column. 172f4a2713aSLionel Sambuc void alignTrailingComments(unsigned Start, unsigned End, unsigned Column); 173f4a2713aSLionel Sambuc 174f4a2713aSLionel Sambuc /// \brief Align escaped newlines over all \c Changes. 175f4a2713aSLionel Sambuc void alignEscapedNewlines(); 176f4a2713aSLionel Sambuc 177f4a2713aSLionel Sambuc /// \brief Align escaped newlines from change \p Start to change \p End at 178f4a2713aSLionel Sambuc /// the specified \p Column. 179f4a2713aSLionel Sambuc void alignEscapedNewlines(unsigned Start, unsigned End, unsigned Column); 180f4a2713aSLionel Sambuc 181f4a2713aSLionel Sambuc /// \brief Fill \c Replaces with the replacements for all effective changes. 182f4a2713aSLionel Sambuc void generateChanges(); 183f4a2713aSLionel Sambuc 184f4a2713aSLionel Sambuc /// \brief Stores \p Text as the replacement for the whitespace in \p Range. 185f4a2713aSLionel Sambuc void storeReplacement(const SourceRange &Range, StringRef Text); 186f4a2713aSLionel Sambuc void appendNewlineText(std::string &Text, unsigned Newlines); 187f4a2713aSLionel Sambuc void appendNewlineText(std::string &Text, unsigned Newlines, 188f4a2713aSLionel Sambuc unsigned PreviousEndOfTokenColumn, 189f4a2713aSLionel Sambuc unsigned EscapedNewlineColumn); 190f4a2713aSLionel Sambuc void appendIndentText(std::string &Text, unsigned IndentLevel, 191f4a2713aSLionel Sambuc unsigned Spaces, unsigned WhitespaceStartColumn); 192f4a2713aSLionel Sambuc 193f4a2713aSLionel Sambuc SmallVector<Change, 16> Changes; 194f4a2713aSLionel Sambuc SourceManager &SourceMgr; 195f4a2713aSLionel Sambuc tooling::Replacements Replaces; 196f4a2713aSLionel Sambuc const FormatStyle &Style; 197f4a2713aSLionel Sambuc bool UseCRLF; 198f4a2713aSLionel Sambuc }; 199f4a2713aSLionel Sambuc 200f4a2713aSLionel Sambuc } // namespace format 201f4a2713aSLionel Sambuc } // namespace clang 202f4a2713aSLionel Sambuc 203*0a6a1f1dSLionel Sambuc #endif 204