WhitespaceManager.h revision 251609
1//===--- WhitespaceManager.h - Format C++ code ------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11/// \brief WhitespaceManager class manages whitespace around tokens and their
12/// replacements.
13///
14//===----------------------------------------------------------------------===//
15
16#ifndef LLVM_CLANG_FORMAT_WHITESPACEMANAGER_H
17#define LLVM_CLANG_FORMAT_WHITESPACEMANAGER_H
18
19#include "TokenAnnotator.h"
20#include "clang/Basic/SourceManager.h"
21#include "clang/Format/Format.h"
22#include <string>
23
24namespace clang {
25namespace format {
26
27/// \brief Manages the whitespaces around tokens and their replacements.
28///
29/// This includes special handling for certain constructs, e.g. the alignment of
30/// trailing line comments.
31class WhitespaceManager {
32public:
33  WhitespaceManager(SourceManager &SourceMgr, const FormatStyle &Style)
34      : SourceMgr(SourceMgr), Style(Style) {}
35
36  /// \brief Replaces the whitespace in front of \p Tok. Only call once for
37  /// each \c AnnotatedToken.
38  void replaceWhitespace(const AnnotatedToken &Tok, unsigned NewLines,
39                         unsigned Spaces, unsigned WhitespaceStartColumn);
40
41  /// \brief Like \c replaceWhitespace, but additionally adds right-aligned
42  /// backslashes to escape newlines inside a preprocessor directive.
43  ///
44  /// This function and \c replaceWhitespace have the same behavior if
45  /// \c Newlines == 0.
46  void replacePPWhitespace(const AnnotatedToken &Tok, unsigned NewLines,
47                           unsigned Spaces, unsigned WhitespaceStartColumn);
48
49  /// \brief Inserts a line break into the middle of a token.
50  ///
51  /// Will break at \p Offset inside \p Tok, putting \p Prefix before the line
52  /// break and \p Postfix before the rest of the token starts in the next line.
53  ///
54  /// \p InPPDirective, \p Spaces, \p WhitespaceStartColumn and \p Style are
55  /// used to generate the correct line break.
56  void breakToken(const FormatToken &Tok, unsigned Offset,
57                  unsigned ReplaceChars, StringRef Prefix, StringRef Postfix,
58                  bool InPPDirective, unsigned Spaces,
59                  unsigned WhitespaceStartColumn);
60
61  /// \brief Returns all the \c Replacements created during formatting.
62  const tooling::Replacements &generateReplacements();
63
64  void addReplacement(const SourceLocation &SourceLoc, unsigned ReplaceChars,
65                      StringRef Text);
66
67  void addUntouchableComment(unsigned Column);
68
69  /// \brief Try to align all stashed comments.
70  void alignComments();
71  /// \brief Try to align all stashed escaped newlines.
72  void alignEscapedNewlines();
73
74private:
75  std::string getNewLineText(unsigned NewLines, unsigned Spaces);
76
77  std::string getNewLineText(unsigned NewLines, unsigned Spaces,
78                             unsigned WhitespaceStartColumn,
79                             unsigned EscapedNewlineColumn);
80
81  /// \brief Structure to store tokens for later layout and alignment.
82  struct StoredToken {
83    StoredToken(SourceLocation ReplacementLoc, unsigned ReplacementLength,
84                unsigned MinColumn, unsigned MaxColumn, unsigned NewLines,
85                unsigned Spaces)
86        : ReplacementLoc(ReplacementLoc), ReplacementLength(ReplacementLength),
87          MinColumn(MinColumn), MaxColumn(MaxColumn), NewLines(NewLines),
88          Spaces(Spaces), Untouchable(false) {}
89    SourceLocation ReplacementLoc;
90    unsigned ReplacementLength;
91    unsigned MinColumn;
92    unsigned MaxColumn;
93    unsigned NewLines;
94    unsigned Spaces;
95    bool Untouchable;
96    std::string Prefix;
97    std::string Postfix;
98  };
99  SmallVector<StoredToken, 16> Comments;
100  SmallVector<StoredToken, 16> EscapedNewlines;
101  typedef SmallVector<StoredToken, 16>::iterator token_iterator;
102
103  /// \brief Put all the comments between \p I and \p E into \p Column.
104  void alignComments(token_iterator I, token_iterator E, unsigned Column);
105
106  /// \brief Stores \p Text as the replacement for the whitespace in front of
107  /// \p Tok.
108  void storeReplacement(SourceLocation Loc, unsigned Length,
109                        const std::string Text);
110
111  SourceManager &SourceMgr;
112  tooling::Replacements Replaces;
113  const FormatStyle &Style;
114};
115
116} // namespace format
117} // namespace clang
118
119#endif // LLVM_CLANG_FORMAT_WHITESPACEMANAGER_H
120