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