TokenAnnotator.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. //===--- TokenAnnotator.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 This file implements a token annotator, i.e. creates
  12. /// \c AnnotatedTokens out of \c FormatTokens with required extra information.
  13. ///
  14. //===----------------------------------------------------------------------===//
  15. #ifndef LLVM_CLANG_LIB_FORMAT_TOKENANNOTATOR_H
  16. #define LLVM_CLANG_LIB_FORMAT_TOKENANNOTATOR_H
  17. #include "UnwrappedLineParser.h"
  18. #include "clang/Format/Format.h"
  19. #include <string>
  20. namespace clang {
  21. class SourceManager;
  22. namespace format {
  23. enum LineType {
  24. LT_Invalid,
  25. LT_ImportStatement,
  26. LT_ObjCDecl, // An @interface, @implementation, or @protocol line.
  27. LT_ObjCMethodDecl,
  28. LT_ObjCProperty, // An @property line.
  29. LT_Other,
  30. LT_PreprocessorDirective,
  31. LT_VirtualFunctionDecl
  32. };
  33. class AnnotatedLine {
  34. public:
  35. AnnotatedLine(const UnwrappedLine &Line)
  36. : First(Line.Tokens.front().Tok), Level(Line.Level),
  37. InPPDirective(Line.InPPDirective),
  38. MustBeDeclaration(Line.MustBeDeclaration), MightBeFunctionDecl(false),
  39. IsMultiVariableDeclStmt(false), Affected(false),
  40. LeadingEmptyLinesAffected(false), ChildrenAffected(false) {
  41. assert(!Line.Tokens.empty());
  42. // Calculate Next and Previous for all tokens. Note that we must overwrite
  43. // Next and Previous for every token, as previous formatting runs might have
  44. // left them in a different state.
  45. First->Previous = nullptr;
  46. FormatToken *Current = First;
  47. for (std::list<UnwrappedLineNode>::const_iterator I = ++Line.Tokens.begin(),
  48. E = Line.Tokens.end();
  49. I != E; ++I) {
  50. const UnwrappedLineNode &Node = *I;
  51. Current->Next = I->Tok;
  52. I->Tok->Previous = Current;
  53. Current = Current->Next;
  54. Current->Children.clear();
  55. for (const auto &Child : Node.Children) {
  56. Children.push_back(new AnnotatedLine(Child));
  57. Current->Children.push_back(Children.back());
  58. }
  59. }
  60. Last = Current;
  61. Last->Next = nullptr;
  62. }
  63. ~AnnotatedLine() {
  64. for (unsigned i = 0, e = Children.size(); i != e; ++i) {
  65. delete Children[i];
  66. }
  67. FormatToken *Current = First;
  68. while (Current) {
  69. Current->Children.clear();
  70. Current->Role.reset();
  71. Current = Current->Next;
  72. }
  73. }
  74. /// \c true if this line starts with the given tokens in order, ignoring
  75. /// comments.
  76. template <typename... Ts> bool startsWith(Ts... Tokens) const {
  77. return startsWith(First, Tokens...);
  78. }
  79. FormatToken *First;
  80. FormatToken *Last;
  81. SmallVector<AnnotatedLine *, 0> Children;
  82. LineType Type;
  83. unsigned Level;
  84. bool InPPDirective;
  85. bool MustBeDeclaration;
  86. bool MightBeFunctionDecl;
  87. bool IsMultiVariableDeclStmt;
  88. /// \c True if this line should be formatted, i.e. intersects directly or
  89. /// indirectly with one of the input ranges.
  90. bool Affected;
  91. /// \c True if the leading empty lines of this line intersect with one of the
  92. /// input ranges.
  93. bool LeadingEmptyLinesAffected;
  94. /// \c True if a one of this line's children intersects with an input range.
  95. bool ChildrenAffected;
  96. private:
  97. // Disallow copying.
  98. AnnotatedLine(const AnnotatedLine &) = delete;
  99. void operator=(const AnnotatedLine &) = delete;
  100. template <typename A, typename... Ts>
  101. bool startsWith(FormatToken *Tok, A K1) const {
  102. while (Tok && Tok->is(tok::comment))
  103. Tok = Tok->Next;
  104. return Tok && Tok->is(K1);
  105. }
  106. template <typename A, typename... Ts>
  107. bool startsWith(FormatToken *Tok, A K1, Ts... Tokens) const {
  108. return startsWith(Tok, K1) && startsWith(Tok->Next, Tokens...);
  109. }
  110. };
  111. /// \brief Determines extra information about the tokens comprising an
  112. /// \c UnwrappedLine.
  113. class TokenAnnotator {
  114. public:
  115. TokenAnnotator(const FormatStyle &Style, const AdditionalKeywords &Keywords)
  116. : Style(Style), Keywords(Keywords) {}
  117. /// \brief Adapts the indent levels of comment lines to the indent of the
  118. /// subsequent line.
  119. // FIXME: Can/should this be done in the UnwrappedLineParser?
  120. void setCommentLineLevels(SmallVectorImpl<AnnotatedLine *> &Lines);
  121. void annotate(AnnotatedLine &Line);
  122. void calculateFormattingInformation(AnnotatedLine &Line);
  123. private:
  124. /// \brief Calculate the penalty for splitting before \c Tok.
  125. unsigned splitPenalty(const AnnotatedLine &Line, const FormatToken &Tok,
  126. bool InFunctionDecl);
  127. bool spaceRequiredBetween(const AnnotatedLine &Line, const FormatToken &Left,
  128. const FormatToken &Right);
  129. bool spaceRequiredBefore(const AnnotatedLine &Line, const FormatToken &Tok);
  130. bool mustBreakBefore(const AnnotatedLine &Line, const FormatToken &Right);
  131. bool canBreakBefore(const AnnotatedLine &Line, const FormatToken &Right);
  132. void printDebugInfo(const AnnotatedLine &Line);
  133. void calculateUnbreakableTailLengths(AnnotatedLine &Line);
  134. const FormatStyle &Style;
  135. const AdditionalKeywords &Keywords;
  136. };
  137. } // end namespace format
  138. } // end namespace clang
  139. #endif