1251609Sdim//===--- WhitespaceManager.h - Format C++ code ------------------*- C++ -*-===//
2251609Sdim//
3251609Sdim//                     The LLVM Compiler Infrastructure
4251609Sdim//
5251609Sdim// This file is distributed under the University of Illinois Open Source
6251609Sdim// License. See LICENSE.TXT for details.
7251609Sdim//
8251609Sdim//===----------------------------------------------------------------------===//
9251609Sdim///
10251609Sdim/// \file
11251609Sdim/// \brief WhitespaceManager class manages whitespace around tokens and their
12251609Sdim/// replacements.
13251609Sdim///
14251609Sdim//===----------------------------------------------------------------------===//
15251609Sdim
16251609Sdim#ifndef LLVM_CLANG_FORMAT_WHITESPACEMANAGER_H
17251609Sdim#define LLVM_CLANG_FORMAT_WHITESPACEMANAGER_H
18251609Sdim
19251609Sdim#include "TokenAnnotator.h"
20251609Sdim#include "clang/Basic/SourceManager.h"
21251609Sdim#include "clang/Format/Format.h"
22251609Sdim#include <string>
23251609Sdim
24251609Sdimnamespace clang {
25251609Sdimnamespace format {
26251609Sdim
27251609Sdim/// \brief Manages the whitespaces around tokens and their replacements.
28251609Sdim///
29251609Sdim/// This includes special handling for certain constructs, e.g. the alignment of
30251609Sdim/// trailing line comments.
31251609Sdimclass WhitespaceManager {
32251609Sdimpublic:
33251609Sdim  WhitespaceManager(SourceManager &SourceMgr, const FormatStyle &Style)
34251609Sdim      : SourceMgr(SourceMgr), Style(Style) {}
35251609Sdim
36251609Sdim  /// \brief Replaces the whitespace in front of \p Tok. Only call once for
37251609Sdim  /// each \c AnnotatedToken.
38251609Sdim  void replaceWhitespace(const AnnotatedToken &Tok, unsigned NewLines,
39251609Sdim                         unsigned Spaces, unsigned WhitespaceStartColumn);
40251609Sdim
41251609Sdim  /// \brief Like \c replaceWhitespace, but additionally adds right-aligned
42251609Sdim  /// backslashes to escape newlines inside a preprocessor directive.
43251609Sdim  ///
44251609Sdim  /// This function and \c replaceWhitespace have the same behavior if
45251609Sdim  /// \c Newlines == 0.
46251609Sdim  void replacePPWhitespace(const AnnotatedToken &Tok, unsigned NewLines,
47251609Sdim                           unsigned Spaces, unsigned WhitespaceStartColumn);
48251609Sdim
49251609Sdim  /// \brief Inserts a line break into the middle of a token.
50251609Sdim  ///
51251609Sdim  /// Will break at \p Offset inside \p Tok, putting \p Prefix before the line
52251609Sdim  /// break and \p Postfix before the rest of the token starts in the next line.
53251609Sdim  ///
54251609Sdim  /// \p InPPDirective, \p Spaces, \p WhitespaceStartColumn and \p Style are
55251609Sdim  /// used to generate the correct line break.
56251609Sdim  void breakToken(const FormatToken &Tok, unsigned Offset,
57251609Sdim                  unsigned ReplaceChars, StringRef Prefix, StringRef Postfix,
58251609Sdim                  bool InPPDirective, unsigned Spaces,
59251609Sdim                  unsigned WhitespaceStartColumn);
60251609Sdim
61251609Sdim  /// \brief Returns all the \c Replacements created during formatting.
62251609Sdim  const tooling::Replacements &generateReplacements();
63251609Sdim
64251609Sdim  void addReplacement(const SourceLocation &SourceLoc, unsigned ReplaceChars,
65251609Sdim                      StringRef Text);
66251609Sdim
67251609Sdim  void addUntouchableComment(unsigned Column);
68251609Sdim
69251609Sdim  /// \brief Try to align all stashed comments.
70251609Sdim  void alignComments();
71251609Sdim  /// \brief Try to align all stashed escaped newlines.
72251609Sdim  void alignEscapedNewlines();
73251609Sdim
74251609Sdimprivate:
75251609Sdim  std::string getNewLineText(unsigned NewLines, unsigned Spaces);
76251609Sdim
77251609Sdim  std::string getNewLineText(unsigned NewLines, unsigned Spaces,
78251609Sdim                             unsigned WhitespaceStartColumn,
79251609Sdim                             unsigned EscapedNewlineColumn);
80251609Sdim
81251609Sdim  /// \brief Structure to store tokens for later layout and alignment.
82251609Sdim  struct StoredToken {
83251609Sdim    StoredToken(SourceLocation ReplacementLoc, unsigned ReplacementLength,
84251609Sdim                unsigned MinColumn, unsigned MaxColumn, unsigned NewLines,
85251609Sdim                unsigned Spaces)
86251609Sdim        : ReplacementLoc(ReplacementLoc), ReplacementLength(ReplacementLength),
87251609Sdim          MinColumn(MinColumn), MaxColumn(MaxColumn), NewLines(NewLines),
88251609Sdim          Spaces(Spaces), Untouchable(false) {}
89251609Sdim    SourceLocation ReplacementLoc;
90251609Sdim    unsigned ReplacementLength;
91251609Sdim    unsigned MinColumn;
92251609Sdim    unsigned MaxColumn;
93251609Sdim    unsigned NewLines;
94251609Sdim    unsigned Spaces;
95251609Sdim    bool Untouchable;
96251609Sdim    std::string Prefix;
97251609Sdim    std::string Postfix;
98251609Sdim  };
99251609Sdim  SmallVector<StoredToken, 16> Comments;
100251609Sdim  SmallVector<StoredToken, 16> EscapedNewlines;
101251609Sdim  typedef SmallVector<StoredToken, 16>::iterator token_iterator;
102251609Sdim
103251609Sdim  /// \brief Put all the comments between \p I and \p E into \p Column.
104251609Sdim  void alignComments(token_iterator I, token_iterator E, unsigned Column);
105251609Sdim
106251609Sdim  /// \brief Stores \p Text as the replacement for the whitespace in front of
107251609Sdim  /// \p Tok.
108251609Sdim  void storeReplacement(SourceLocation Loc, unsigned Length,
109251609Sdim                        const std::string Text);
110251609Sdim
111251609Sdim  SourceManager &SourceMgr;
112251609Sdim  tooling::Replacements Replaces;
113251609Sdim  const FormatStyle &Style;
114251609Sdim};
115251609Sdim
116251609Sdim} // namespace format
117251609Sdim} // namespace clang
118251609Sdim
119251609Sdim#endif // LLVM_CLANG_FORMAT_WHITESPACEMANAGER_H
120