1e5dd7070Spatrick //===--- BreakableToken.h - Format C++ code ---------------------*- C++ -*-===// 2e5dd7070Spatrick // 3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information. 5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e5dd7070Spatrick // 7e5dd7070Spatrick //===----------------------------------------------------------------------===// 8e5dd7070Spatrick /// 9e5dd7070Spatrick /// \file 10e5dd7070Spatrick /// Declares BreakableToken, BreakableStringLiteral, BreakableComment, 11e5dd7070Spatrick /// BreakableBlockComment and BreakableLineCommentSection classes, that contain 12e5dd7070Spatrick /// token type-specific logic to break long lines in tokens and reflow content 13e5dd7070Spatrick /// between tokens. 14e5dd7070Spatrick /// 15e5dd7070Spatrick //===----------------------------------------------------------------------===// 16e5dd7070Spatrick 17e5dd7070Spatrick #ifndef LLVM_CLANG_LIB_FORMAT_BREAKABLETOKEN_H 18e5dd7070Spatrick #define LLVM_CLANG_LIB_FORMAT_BREAKABLETOKEN_H 19e5dd7070Spatrick 20e5dd7070Spatrick #include "Encoding.h" 21e5dd7070Spatrick #include "TokenAnnotator.h" 22e5dd7070Spatrick #include "WhitespaceManager.h" 23e5dd7070Spatrick #include "llvm/ADT/StringSet.h" 24e5dd7070Spatrick #include "llvm/Support/Regex.h" 25e5dd7070Spatrick #include <utility> 26e5dd7070Spatrick 27e5dd7070Spatrick namespace clang { 28e5dd7070Spatrick namespace format { 29e5dd7070Spatrick 30e5dd7070Spatrick /// Checks if \p Token switches formatting, like /* clang-format off */. 31e5dd7070Spatrick /// \p Token must be a comment. 32e5dd7070Spatrick bool switchesFormatting(const FormatToken &Token); 33e5dd7070Spatrick 34e5dd7070Spatrick struct FormatStyle; 35e5dd7070Spatrick 36e5dd7070Spatrick /// Base class for tokens / ranges of tokens that can allow breaking 37e5dd7070Spatrick /// within the tokens - for example, to avoid whitespace beyond the column 38e5dd7070Spatrick /// limit, or to reflow text. 39e5dd7070Spatrick /// 40e5dd7070Spatrick /// Generally, a breakable token consists of logical lines, addressed by a line 41e5dd7070Spatrick /// index. For example, in a sequence of line comments, each line comment is its 42e5dd7070Spatrick /// own logical line; similarly, for a block comment, each line in the block 43e5dd7070Spatrick /// comment is on its own logical line. 44e5dd7070Spatrick /// 45e5dd7070Spatrick /// There are two methods to compute the layout of the token: 46e5dd7070Spatrick /// - getRangeLength measures the number of columns needed for a range of text 47e5dd7070Spatrick /// within a logical line, and 48e5dd7070Spatrick /// - getContentStartColumn returns the start column at which we want the 49e5dd7070Spatrick /// content of a logical line to start (potentially after introducing a line 50e5dd7070Spatrick /// break). 51e5dd7070Spatrick /// 52e5dd7070Spatrick /// The mechanism to adapt the layout of the breakable token is organised 53e5dd7070Spatrick /// around the concept of a \c Split, which is a whitespace range that signifies 54e5dd7070Spatrick /// a position of the content of a token where a reformatting might be done. 55e5dd7070Spatrick /// 56e5dd7070Spatrick /// Operating with splits is divided into two operations: 57e5dd7070Spatrick /// - getSplit, for finding a split starting at a position, 58e5dd7070Spatrick /// - insertBreak, for executing the split using a whitespace manager. 59e5dd7070Spatrick /// 60e5dd7070Spatrick /// There is a pair of operations that are used to compress a long whitespace 61e5dd7070Spatrick /// range with a single space if that will bring the line length under the 62e5dd7070Spatrick /// column limit: 63e5dd7070Spatrick /// - getLineLengthAfterCompression, for calculating the size in columns of the 64e5dd7070Spatrick /// line after a whitespace range has been compressed, and 65e5dd7070Spatrick /// - compressWhitespace, for executing the whitespace compression using a 66e5dd7070Spatrick /// whitespace manager; note that the compressed whitespace may be in the 67e5dd7070Spatrick /// middle of the original line and of the reformatted line. 68e5dd7070Spatrick /// 69e5dd7070Spatrick /// For tokens where the whitespace before each line needs to be also 70e5dd7070Spatrick /// reformatted, for example for tokens supporting reflow, there are analogous 71e5dd7070Spatrick /// operations that might be executed before the main line breaking occurs: 72e5dd7070Spatrick /// - getReflowSplit, for finding a split such that the content preceding it 73e5dd7070Spatrick /// needs to be specially reflown, 74e5dd7070Spatrick /// - reflow, for executing the split using a whitespace manager, 75e5dd7070Spatrick /// - introducesBreakBefore, for checking if reformatting the beginning 76e5dd7070Spatrick /// of the content introduces a line break before it, 77e5dd7070Spatrick /// - adaptStartOfLine, for executing the reflow using a whitespace 78e5dd7070Spatrick /// manager. 79e5dd7070Spatrick /// 80e5dd7070Spatrick /// For tokens that require the whitespace after the last line to be 81e5dd7070Spatrick /// reformatted, for example in multiline jsdoc comments that require the 82e5dd7070Spatrick /// trailing '*/' to be on a line of itself, there are analogous operations 83e5dd7070Spatrick /// that might be executed after the last line has been reformatted: 84e5dd7070Spatrick /// - getSplitAfterLastLine, for finding a split after the last line that needs 85e5dd7070Spatrick /// to be reflown, 86e5dd7070Spatrick /// - replaceWhitespaceAfterLastLine, for executing the reflow using a 87e5dd7070Spatrick /// whitespace manager. 88e5dd7070Spatrick /// 89e5dd7070Spatrick class BreakableToken { 90e5dd7070Spatrick public: 91e5dd7070Spatrick /// Contains starting character index and length of split. 92e5dd7070Spatrick typedef std::pair<StringRef::size_type, unsigned> Split; 93e5dd7070Spatrick ~BreakableToken()94e5dd7070Spatrick virtual ~BreakableToken() {} 95e5dd7070Spatrick 96e5dd7070Spatrick /// Returns the number of lines in this token in the original code. 97e5dd7070Spatrick virtual unsigned getLineCount() const = 0; 98e5dd7070Spatrick 99e5dd7070Spatrick /// Returns the number of columns required to format the text in the 100e5dd7070Spatrick /// byte range [\p Offset, \p Offset \c + \p Length). 101e5dd7070Spatrick /// 102e5dd7070Spatrick /// \p Offset is the byte offset from the start of the content of the line 103e5dd7070Spatrick /// at \p LineIndex. 104e5dd7070Spatrick /// 105e5dd7070Spatrick /// \p StartColumn is the column at which the text starts in the formatted 106e5dd7070Spatrick /// file, needed to compute tab stops correctly. 107e5dd7070Spatrick virtual unsigned getRangeLength(unsigned LineIndex, unsigned Offset, 108e5dd7070Spatrick StringRef::size_type Length, 109e5dd7070Spatrick unsigned StartColumn) const = 0; 110e5dd7070Spatrick 111e5dd7070Spatrick /// Returns the number of columns required to format the text following 112e5dd7070Spatrick /// the byte \p Offset in the line \p LineIndex, including potentially 113e5dd7070Spatrick /// unbreakable sequences of tokens following after the end of the token. 114e5dd7070Spatrick /// 115e5dd7070Spatrick /// \p Offset is the byte offset from the start of the content of the line 116e5dd7070Spatrick /// at \p LineIndex. 117e5dd7070Spatrick /// 118e5dd7070Spatrick /// \p StartColumn is the column at which the text starts in the formatted 119e5dd7070Spatrick /// file, needed to compute tab stops correctly. 120e5dd7070Spatrick /// 121e5dd7070Spatrick /// For breakable tokens that never use extra space at the end of a line, this 122e5dd7070Spatrick /// is equivalent to getRangeLength with a Length of StringRef::npos. getRemainingLength(unsigned LineIndex,unsigned Offset,unsigned StartColumn)123e5dd7070Spatrick virtual unsigned getRemainingLength(unsigned LineIndex, unsigned Offset, 124e5dd7070Spatrick unsigned StartColumn) const { 125e5dd7070Spatrick return getRangeLength(LineIndex, Offset, StringRef::npos, StartColumn); 126e5dd7070Spatrick } 127e5dd7070Spatrick 128e5dd7070Spatrick /// Returns the column at which content in line \p LineIndex starts, 129e5dd7070Spatrick /// assuming no reflow. 130e5dd7070Spatrick /// 131e5dd7070Spatrick /// If \p Break is true, returns the column at which the line should start 132e5dd7070Spatrick /// after the line break. 133e5dd7070Spatrick /// If \p Break is false, returns the column at which the line itself will 134e5dd7070Spatrick /// start. 135e5dd7070Spatrick virtual unsigned getContentStartColumn(unsigned LineIndex, 136e5dd7070Spatrick bool Break) const = 0; 137e5dd7070Spatrick 138e5dd7070Spatrick /// Returns additional content indent required for the second line after the 139e5dd7070Spatrick /// content at line \p LineIndex is broken. 140e5dd7070Spatrick /// 141e5dd7070Spatrick // (Next lines do not start with `///` since otherwise -Wdocumentation picks 142e5dd7070Spatrick // up the example annotations and generates warnings for them) 143e5dd7070Spatrick // For example, Javadoc @param annotations require and indent of 4 spaces and 144e5dd7070Spatrick // in this example getContentIndex(1) returns 4. 145e5dd7070Spatrick // /** 146e5dd7070Spatrick // * @param loooooooooooooong line 147e5dd7070Spatrick // * continuation 148e5dd7070Spatrick // */ getContentIndent(unsigned LineIndex)149e5dd7070Spatrick virtual unsigned getContentIndent(unsigned LineIndex) const { return 0; } 150e5dd7070Spatrick 151e5dd7070Spatrick /// Returns a range (offset, length) at which to break the line at 152e5dd7070Spatrick /// \p LineIndex, if previously broken at \p TailOffset. If possible, do not 153e5dd7070Spatrick /// violate \p ColumnLimit, assuming the text starting at \p TailOffset in 154e5dd7070Spatrick /// the token is formatted starting at ContentStartColumn in the reformatted 155e5dd7070Spatrick /// file. 156e5dd7070Spatrick virtual Split getSplit(unsigned LineIndex, unsigned TailOffset, 157e5dd7070Spatrick unsigned ColumnLimit, unsigned ContentStartColumn, 158e5dd7070Spatrick const llvm::Regex &CommentPragmasRegex) const = 0; 159e5dd7070Spatrick 160e5dd7070Spatrick /// Emits the previously retrieved \p Split via \p Whitespaces. 161e5dd7070Spatrick virtual void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split, 162e5dd7070Spatrick unsigned ContentIndent, 163e5dd7070Spatrick WhitespaceManager &Whitespaces) const = 0; 164e5dd7070Spatrick 165e5dd7070Spatrick /// Returns the number of columns needed to format 166e5dd7070Spatrick /// \p RemainingTokenColumns, assuming that Split is within the range measured 167e5dd7070Spatrick /// by \p RemainingTokenColumns, and that the whitespace in Split is reduced 168e5dd7070Spatrick /// to a single space. 169e5dd7070Spatrick unsigned getLengthAfterCompression(unsigned RemainingTokenColumns, 170e5dd7070Spatrick Split Split) const; 171e5dd7070Spatrick 172e5dd7070Spatrick /// Replaces the whitespace range described by \p Split with a single 173e5dd7070Spatrick /// space. 174e5dd7070Spatrick virtual void compressWhitespace(unsigned LineIndex, unsigned TailOffset, 175e5dd7070Spatrick Split Split, 176e5dd7070Spatrick WhitespaceManager &Whitespaces) const = 0; 177e5dd7070Spatrick 178e5dd7070Spatrick /// Returns whether the token supports reflowing text. supportsReflow()179e5dd7070Spatrick virtual bool supportsReflow() const { return false; } 180e5dd7070Spatrick 181e5dd7070Spatrick /// Returns a whitespace range (offset, length) of the content at \p 182e5dd7070Spatrick /// LineIndex such that the content of that line is reflown to the end of the 183e5dd7070Spatrick /// previous one. 184e5dd7070Spatrick /// 185e5dd7070Spatrick /// Returning (StringRef::npos, 0) indicates reflowing is not possible. 186e5dd7070Spatrick /// 187e5dd7070Spatrick /// The range will include any whitespace preceding the specified line's 188e5dd7070Spatrick /// content. 189e5dd7070Spatrick /// 190e5dd7070Spatrick /// If the split is not contained within one token, for example when reflowing 191e5dd7070Spatrick /// line comments, returns (0, <length>). getReflowSplit(unsigned LineIndex,const llvm::Regex & CommentPragmasRegex)192e5dd7070Spatrick virtual Split getReflowSplit(unsigned LineIndex, 193e5dd7070Spatrick const llvm::Regex &CommentPragmasRegex) const { 194e5dd7070Spatrick return Split(StringRef::npos, 0); 195e5dd7070Spatrick } 196e5dd7070Spatrick 197e5dd7070Spatrick /// Reflows the current line into the end of the previous one. reflow(unsigned LineIndex,WhitespaceManager & Whitespaces)198e5dd7070Spatrick virtual void reflow(unsigned LineIndex, 199e5dd7070Spatrick WhitespaceManager &Whitespaces) const {} 200e5dd7070Spatrick 201e5dd7070Spatrick /// Returns whether there will be a line break at the start of the 202e5dd7070Spatrick /// token. introducesBreakBeforeToken()203e5dd7070Spatrick virtual bool introducesBreakBeforeToken() const { return false; } 204e5dd7070Spatrick 205e5dd7070Spatrick /// Replaces the whitespace between \p LineIndex-1 and \p LineIndex. adaptStartOfLine(unsigned LineIndex,WhitespaceManager & Whitespaces)206e5dd7070Spatrick virtual void adaptStartOfLine(unsigned LineIndex, 207e5dd7070Spatrick WhitespaceManager &Whitespaces) const {} 208e5dd7070Spatrick 209e5dd7070Spatrick /// Returns a whitespace range (offset, length) of the content at 210e5dd7070Spatrick /// the last line that needs to be reformatted after the last line has been 211e5dd7070Spatrick /// reformatted. 212e5dd7070Spatrick /// 213e5dd7070Spatrick /// A result having offset == StringRef::npos means that no reformat is 214e5dd7070Spatrick /// necessary. getSplitAfterLastLine(unsigned TailOffset)215e5dd7070Spatrick virtual Split getSplitAfterLastLine(unsigned TailOffset) const { 216e5dd7070Spatrick return Split(StringRef::npos, 0); 217e5dd7070Spatrick } 218e5dd7070Spatrick 219e5dd7070Spatrick /// Replaces the whitespace from \p SplitAfterLastLine on the last line 220e5dd7070Spatrick /// after the last line has been formatted by performing a reformatting. replaceWhitespaceAfterLastLine(unsigned TailOffset,Split SplitAfterLastLine,WhitespaceManager & Whitespaces)221e5dd7070Spatrick void replaceWhitespaceAfterLastLine(unsigned TailOffset, 222e5dd7070Spatrick Split SplitAfterLastLine, 223e5dd7070Spatrick WhitespaceManager &Whitespaces) const { 224e5dd7070Spatrick insertBreak(getLineCount() - 1, TailOffset, SplitAfterLastLine, 225e5dd7070Spatrick /*ContentIndent=*/0, Whitespaces); 226e5dd7070Spatrick } 227e5dd7070Spatrick 228e5dd7070Spatrick /// Updates the next token of \p State to the next token after this 229e5dd7070Spatrick /// one. This can be used when this token manages a set of underlying tokens 230e5dd7070Spatrick /// as a unit and is responsible for the formatting of the them. updateNextToken(LineState & State)231e5dd7070Spatrick virtual void updateNextToken(LineState &State) const {} 232e5dd7070Spatrick 233e5dd7070Spatrick protected: BreakableToken(const FormatToken & Tok,bool InPPDirective,encoding::Encoding Encoding,const FormatStyle & Style)234e5dd7070Spatrick BreakableToken(const FormatToken &Tok, bool InPPDirective, 235e5dd7070Spatrick encoding::Encoding Encoding, const FormatStyle &Style) 236e5dd7070Spatrick : Tok(Tok), InPPDirective(InPPDirective), Encoding(Encoding), 237e5dd7070Spatrick Style(Style) {} 238e5dd7070Spatrick 239e5dd7070Spatrick const FormatToken &Tok; 240e5dd7070Spatrick const bool InPPDirective; 241e5dd7070Spatrick const encoding::Encoding Encoding; 242e5dd7070Spatrick const FormatStyle &Style; 243e5dd7070Spatrick }; 244e5dd7070Spatrick 245e5dd7070Spatrick class BreakableStringLiteral : public BreakableToken { 246e5dd7070Spatrick public: 247e5dd7070Spatrick /// Creates a breakable token for a single line string literal. 248e5dd7070Spatrick /// 249e5dd7070Spatrick /// \p StartColumn specifies the column in which the token will start 250e5dd7070Spatrick /// after formatting. 251e5dd7070Spatrick BreakableStringLiteral(const FormatToken &Tok, unsigned StartColumn, 252e5dd7070Spatrick StringRef Prefix, StringRef Postfix, 253e5dd7070Spatrick unsigned UnbreakableTailLength, bool InPPDirective, 254e5dd7070Spatrick encoding::Encoding Encoding, const FormatStyle &Style); 255e5dd7070Spatrick 256e5dd7070Spatrick Split getSplit(unsigned LineIndex, unsigned TailOffset, unsigned ColumnLimit, 257e5dd7070Spatrick unsigned ContentStartColumn, 258e5dd7070Spatrick const llvm::Regex &CommentPragmasRegex) const override; 259e5dd7070Spatrick void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split, 260e5dd7070Spatrick unsigned ContentIndent, 261e5dd7070Spatrick WhitespaceManager &Whitespaces) const override; compressWhitespace(unsigned LineIndex,unsigned TailOffset,Split Split,WhitespaceManager & Whitespaces)262e5dd7070Spatrick void compressWhitespace(unsigned LineIndex, unsigned TailOffset, Split Split, 263e5dd7070Spatrick WhitespaceManager &Whitespaces) const override {} 264e5dd7070Spatrick unsigned getLineCount() const override; 265e5dd7070Spatrick unsigned getRangeLength(unsigned LineIndex, unsigned Offset, 266e5dd7070Spatrick StringRef::size_type Length, 267e5dd7070Spatrick unsigned StartColumn) const override; 268e5dd7070Spatrick unsigned getRemainingLength(unsigned LineIndex, unsigned Offset, 269e5dd7070Spatrick unsigned StartColumn) const override; 270e5dd7070Spatrick unsigned getContentStartColumn(unsigned LineIndex, bool Break) const override; 271e5dd7070Spatrick 272e5dd7070Spatrick protected: 273e5dd7070Spatrick // The column in which the token starts. 274e5dd7070Spatrick unsigned StartColumn; 275e5dd7070Spatrick // The prefix a line needs after a break in the token. 276e5dd7070Spatrick StringRef Prefix; 277e5dd7070Spatrick // The postfix a line needs before introducing a break. 278e5dd7070Spatrick StringRef Postfix; 279e5dd7070Spatrick // The token text excluding the prefix and postfix. 280e5dd7070Spatrick StringRef Line; 281e5dd7070Spatrick // Length of the sequence of tokens after this string literal that cannot 282e5dd7070Spatrick // contain line breaks. 283e5dd7070Spatrick unsigned UnbreakableTailLength; 284e5dd7070Spatrick }; 285e5dd7070Spatrick 286e5dd7070Spatrick class BreakableComment : public BreakableToken { 287e5dd7070Spatrick protected: 288e5dd7070Spatrick /// Creates a breakable token for a comment. 289e5dd7070Spatrick /// 290e5dd7070Spatrick /// \p StartColumn specifies the column in which the comment will start after 291e5dd7070Spatrick /// formatting. 292e5dd7070Spatrick BreakableComment(const FormatToken &Token, unsigned StartColumn, 293e5dd7070Spatrick bool InPPDirective, encoding::Encoding Encoding, 294e5dd7070Spatrick const FormatStyle &Style); 295e5dd7070Spatrick 296e5dd7070Spatrick public: supportsReflow()297e5dd7070Spatrick bool supportsReflow() const override { return true; } 298e5dd7070Spatrick unsigned getLineCount() const override; 299e5dd7070Spatrick Split getSplit(unsigned LineIndex, unsigned TailOffset, unsigned ColumnLimit, 300e5dd7070Spatrick unsigned ContentStartColumn, 301e5dd7070Spatrick const llvm::Regex &CommentPragmasRegex) const override; 302e5dd7070Spatrick void compressWhitespace(unsigned LineIndex, unsigned TailOffset, Split Split, 303e5dd7070Spatrick WhitespaceManager &Whitespaces) const override; 304e5dd7070Spatrick 305e5dd7070Spatrick protected: 306e5dd7070Spatrick // Returns the token containing the line at LineIndex. 307e5dd7070Spatrick const FormatToken &tokenAt(unsigned LineIndex) const; 308e5dd7070Spatrick 309e5dd7070Spatrick // Checks if the content of line LineIndex may be reflown with the previous 310e5dd7070Spatrick // line. 311e5dd7070Spatrick virtual bool mayReflow(unsigned LineIndex, 312e5dd7070Spatrick const llvm::Regex &CommentPragmasRegex) const = 0; 313e5dd7070Spatrick 314e5dd7070Spatrick // Contains the original text of the lines of the block comment. 315e5dd7070Spatrick // 316e5dd7070Spatrick // In case of a block comments, excludes the leading /* in the first line and 317e5dd7070Spatrick // trailing */ in the last line. In case of line comments, excludes the 318e5dd7070Spatrick // leading // and spaces. 319e5dd7070Spatrick SmallVector<StringRef, 16> Lines; 320e5dd7070Spatrick 321e5dd7070Spatrick // Contains the text of the lines excluding all leading and trailing 322e5dd7070Spatrick // whitespace between the lines. Note that the decoration (if present) is also 323e5dd7070Spatrick // not considered part of the text. 324e5dd7070Spatrick SmallVector<StringRef, 16> Content; 325e5dd7070Spatrick 326e5dd7070Spatrick // Tokens[i] contains a reference to the token containing Lines[i] if the 327e5dd7070Spatrick // whitespace range before that token is managed by this block. 328e5dd7070Spatrick // Otherwise, Tokens[i] is a null pointer. 329e5dd7070Spatrick SmallVector<FormatToken *, 16> Tokens; 330e5dd7070Spatrick 331e5dd7070Spatrick // ContentColumn[i] is the target column at which Content[i] should be. 332e5dd7070Spatrick // Note that this excludes a leading "* " or "*" in case of block comments 333e5dd7070Spatrick // where all lines have a "*" prefix, or the leading "// " or "//" in case of 334e5dd7070Spatrick // line comments. 335e5dd7070Spatrick // 336e5dd7070Spatrick // In block comments, the first line's target column is always positive. The 337e5dd7070Spatrick // remaining lines' target columns are relative to the first line to allow 338e5dd7070Spatrick // correct indentation of comments in \c WhitespaceManager. Thus they can be 339e5dd7070Spatrick // negative as well (in case the first line needs to be unindented more than 340e5dd7070Spatrick // there's actual whitespace in another line). 341e5dd7070Spatrick SmallVector<int, 16> ContentColumn; 342e5dd7070Spatrick 343e5dd7070Spatrick // The intended start column of the first line of text from this section. 344e5dd7070Spatrick unsigned StartColumn; 345e5dd7070Spatrick 346e5dd7070Spatrick // The prefix to use in front a line that has been reflown up. 347e5dd7070Spatrick // For example, when reflowing the second line after the first here: 348e5dd7070Spatrick // // comment 1 349e5dd7070Spatrick // // comment 2 350e5dd7070Spatrick // we expect: 351e5dd7070Spatrick // // comment 1 comment 2 352e5dd7070Spatrick // and not: 353e5dd7070Spatrick // // comment 1comment 2 354e5dd7070Spatrick StringRef ReflowPrefix = " "; 355e5dd7070Spatrick }; 356e5dd7070Spatrick 357e5dd7070Spatrick class BreakableBlockComment : public BreakableComment { 358e5dd7070Spatrick public: 359e5dd7070Spatrick BreakableBlockComment(const FormatToken &Token, unsigned StartColumn, 360e5dd7070Spatrick unsigned OriginalStartColumn, bool FirstInLine, 361e5dd7070Spatrick bool InPPDirective, encoding::Encoding Encoding, 362e5dd7070Spatrick const FormatStyle &Style, bool UseCRLF); 363e5dd7070Spatrick 364e5dd7070Spatrick Split getSplit(unsigned LineIndex, unsigned TailOffset, unsigned ColumnLimit, 365e5dd7070Spatrick unsigned ContentStartColumn, 366e5dd7070Spatrick const llvm::Regex &CommentPragmasRegex) const override; 367e5dd7070Spatrick unsigned getRangeLength(unsigned LineIndex, unsigned Offset, 368e5dd7070Spatrick StringRef::size_type Length, 369e5dd7070Spatrick unsigned StartColumn) const override; 370e5dd7070Spatrick unsigned getRemainingLength(unsigned LineIndex, unsigned Offset, 371e5dd7070Spatrick unsigned StartColumn) const override; 372e5dd7070Spatrick unsigned getContentStartColumn(unsigned LineIndex, bool Break) const override; 373e5dd7070Spatrick unsigned getContentIndent(unsigned LineIndex) const override; 374e5dd7070Spatrick void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split, 375e5dd7070Spatrick unsigned ContentIndent, 376e5dd7070Spatrick WhitespaceManager &Whitespaces) const override; 377e5dd7070Spatrick Split getReflowSplit(unsigned LineIndex, 378e5dd7070Spatrick const llvm::Regex &CommentPragmasRegex) const override; 379e5dd7070Spatrick void reflow(unsigned LineIndex, 380e5dd7070Spatrick WhitespaceManager &Whitespaces) const override; 381e5dd7070Spatrick bool introducesBreakBeforeToken() const override; 382e5dd7070Spatrick void adaptStartOfLine(unsigned LineIndex, 383e5dd7070Spatrick WhitespaceManager &Whitespaces) const override; 384e5dd7070Spatrick Split getSplitAfterLastLine(unsigned TailOffset) const override; 385e5dd7070Spatrick 386e5dd7070Spatrick bool mayReflow(unsigned LineIndex, 387e5dd7070Spatrick const llvm::Regex &CommentPragmasRegex) const override; 388e5dd7070Spatrick 389e5dd7070Spatrick // Contains Javadoc annotations that require additional indent when continued 390e5dd7070Spatrick // on multiple lines. 391e5dd7070Spatrick static const llvm::StringSet<> ContentIndentingJavadocAnnotations; 392e5dd7070Spatrick 393e5dd7070Spatrick private: 394e5dd7070Spatrick // Rearranges the whitespace between Lines[LineIndex-1] and Lines[LineIndex]. 395e5dd7070Spatrick // 396e5dd7070Spatrick // Updates Content[LineIndex-1] and Content[LineIndex] by stripping off 397e5dd7070Spatrick // leading and trailing whitespace. 398e5dd7070Spatrick // 399e5dd7070Spatrick // Sets ContentColumn to the intended column in which the text at 400e5dd7070Spatrick // Lines[LineIndex] starts (note that the decoration, if present, is not 401e5dd7070Spatrick // considered part of the text). 402e5dd7070Spatrick void adjustWhitespace(unsigned LineIndex, int IndentDelta); 403e5dd7070Spatrick 404e5dd7070Spatrick // The column at which the text of a broken line should start. 405e5dd7070Spatrick // Note that an optional decoration would go before that column. 406e5dd7070Spatrick // IndentAtLineBreak is a uniform position for all lines in a block comment, 407e5dd7070Spatrick // regardless of their relative position. 408e5dd7070Spatrick // FIXME: Revisit the decision to do this; the main reason was to support 409e5dd7070Spatrick // patterns like 410e5dd7070Spatrick // /**************//** 411e5dd7070Spatrick // * Comment 412e5dd7070Spatrick // We could also support such patterns by special casing the first line 413e5dd7070Spatrick // instead. 414e5dd7070Spatrick unsigned IndentAtLineBreak; 415e5dd7070Spatrick 416e5dd7070Spatrick // This is to distinguish between the case when the last line was empty and 417e5dd7070Spatrick // the case when it started with a decoration ("*" or "* "). 418e5dd7070Spatrick bool LastLineNeedsDecoration; 419e5dd7070Spatrick 420e5dd7070Spatrick // Either "* " if all lines begin with a "*", or empty. 421e5dd7070Spatrick StringRef Decoration; 422e5dd7070Spatrick 423e5dd7070Spatrick // If this block comment has decorations, this is the column of the start of 424e5dd7070Spatrick // the decorations. 425e5dd7070Spatrick unsigned DecorationColumn; 426e5dd7070Spatrick 427e5dd7070Spatrick // If true, make sure that the opening '/**' and the closing '*/' ends on a 428e5dd7070Spatrick // line of itself. Styles like jsdoc require this for multiline comments. 429e5dd7070Spatrick bool DelimitersOnNewline; 430e5dd7070Spatrick 431e5dd7070Spatrick // Length of the sequence of tokens after this string literal that cannot 432e5dd7070Spatrick // contain line breaks. 433e5dd7070Spatrick unsigned UnbreakableTailLength; 434e5dd7070Spatrick }; 435e5dd7070Spatrick 436e5dd7070Spatrick class BreakableLineCommentSection : public BreakableComment { 437e5dd7070Spatrick public: 438e5dd7070Spatrick BreakableLineCommentSection(const FormatToken &Token, unsigned StartColumn, 439e5dd7070Spatrick bool InPPDirective, encoding::Encoding Encoding, 440e5dd7070Spatrick const FormatStyle &Style); 441e5dd7070Spatrick 442e5dd7070Spatrick unsigned getRangeLength(unsigned LineIndex, unsigned Offset, 443e5dd7070Spatrick StringRef::size_type Length, 444e5dd7070Spatrick unsigned StartColumn) const override; 445e5dd7070Spatrick unsigned getContentStartColumn(unsigned LineIndex, bool Break) const override; 446e5dd7070Spatrick void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split, 447e5dd7070Spatrick unsigned ContentIndent, 448e5dd7070Spatrick WhitespaceManager &Whitespaces) const override; 449e5dd7070Spatrick Split getReflowSplit(unsigned LineIndex, 450e5dd7070Spatrick const llvm::Regex &CommentPragmasRegex) const override; 451e5dd7070Spatrick void reflow(unsigned LineIndex, 452e5dd7070Spatrick WhitespaceManager &Whitespaces) const override; 453e5dd7070Spatrick void adaptStartOfLine(unsigned LineIndex, 454e5dd7070Spatrick WhitespaceManager &Whitespaces) const override; 455e5dd7070Spatrick void updateNextToken(LineState &State) const override; 456e5dd7070Spatrick bool mayReflow(unsigned LineIndex, 457e5dd7070Spatrick const llvm::Regex &CommentPragmasRegex) const override; 458e5dd7070Spatrick 459e5dd7070Spatrick private: 460e5dd7070Spatrick // OriginalPrefix[i] contains the original prefix of line i, including 461e5dd7070Spatrick // trailing whitespace before the start of the content. The indentation 462e5dd7070Spatrick // preceding the prefix is not included. 463e5dd7070Spatrick // For example, if the line is: 464e5dd7070Spatrick // // content 465e5dd7070Spatrick // then the original prefix is "// ". 466e5dd7070Spatrick SmallVector<StringRef, 16> OriginalPrefix; 467e5dd7070Spatrick 468*a9ac8606Spatrick /// Prefix[i] + SpacesToAdd[i] contains the intended leading "//" with 469*a9ac8606Spatrick /// trailing spaces to account for the indentation of content within the 470*a9ac8606Spatrick /// comment at line i after formatting. It can be different than the original 471*a9ac8606Spatrick /// prefix. 472*a9ac8606Spatrick /// When the original line starts like this: 473*a9ac8606Spatrick /// //content 474*a9ac8606Spatrick /// Then the OriginalPrefix[i] is "//", but the Prefix[i] is "// " in the LLVM 475*a9ac8606Spatrick /// style. 476*a9ac8606Spatrick /// When the line starts like: 477*a9ac8606Spatrick /// // content 478*a9ac8606Spatrick /// And we want to remove the spaces the OriginalPrefix[i] is "// " and 479*a9ac8606Spatrick /// Prefix[i] is "//". 480*a9ac8606Spatrick SmallVector<std::string, 16> Prefix; 481e5dd7070Spatrick 482*a9ac8606Spatrick /// How many spaces are added or removed from the OriginalPrefix to form 483*a9ac8606Spatrick /// Prefix. 484*a9ac8606Spatrick SmallVector<int, 16> PrefixSpaceChange; 485e5dd7070Spatrick 486e5dd7070Spatrick /// The token to which the last line of this breakable token belongs 487e5dd7070Spatrick /// to; nullptr if that token is the initial token. 488e5dd7070Spatrick /// 489e5dd7070Spatrick /// The distinction is because if the token of the last line of this breakable 490e5dd7070Spatrick /// token is distinct from the initial token, this breakable token owns the 491e5dd7070Spatrick /// whitespace before the token of the last line, and the whitespace manager 492e5dd7070Spatrick /// must be able to modify it. 493e5dd7070Spatrick FormatToken *LastLineTok = nullptr; 494e5dd7070Spatrick }; 495e5dd7070Spatrick } // namespace format 496e5dd7070Spatrick } // namespace clang 497e5dd7070Spatrick 498e5dd7070Spatrick #endif 499