TokenAnnotator.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. //===--- TokenAnnotator.h - Format C++ code ---------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. ///
  9. /// \file
  10. /// This file implements a token annotator, i.e. creates
  11. /// \c AnnotatedTokens out of \c FormatTokens with required extra information.
  12. ///
  13. //===----------------------------------------------------------------------===//
  14. #ifndef LLVM_CLANG_LIB_FORMAT_TOKENANNOTATOR_H
  15. #define LLVM_CLANG_LIB_FORMAT_TOKENANNOTATOR_H
  16. #include "UnwrappedLineParser.h"
  17. #include "clang/Format/Format.h"
  18. namespace clang {
  19. class SourceManager;
  20. namespace format {
  21. enum LineType {
  22. LT_Invalid,
  23. LT_ImportStatement,
  24. LT_ObjCDecl, // An @interface, @implementation, or @protocol line.
  25. LT_ObjCMethodDecl,
  26. LT_ObjCProperty, // An @property line.
  27. LT_Other,
  28. LT_PreprocessorDirective,
  29. LT_VirtualFunctionDecl
  30. };
  31. class AnnotatedLine {
  32. public:
  33. AnnotatedLine(const UnwrappedLine &Line)
  34. : First(Line.Tokens.front().Tok), Level(Line.Level),
  35. MatchingOpeningBlockLineIndex(Line.MatchingOpeningBlockLineIndex),
  36. MatchingClosingBlockLineIndex(Line.MatchingClosingBlockLineIndex),
  37. InPPDirective(Line.InPPDirective),
  38. MustBeDeclaration(Line.MustBeDeclaration), MightBeFunctionDecl(false),
  39. IsMultiVariableDeclStmt(false), Affected(false),
  40. LeadingEmptyLinesAffected(false), ChildrenAffected(false),
  41. FirstStartColumn(Line.FirstStartColumn) {
  42. assert(!Line.Tokens.empty());
  43. // Calculate Next and Previous for all tokens. Note that we must overwrite
  44. // Next and Previous for every token, as previous formatting runs might have
  45. // left them in a different state.
  46. First->Previous = nullptr;
  47. FormatToken *Current = First;
  48. for (std::list<UnwrappedLineNode>::const_iterator I = ++Line.Tokens.begin(),
  49. E = Line.Tokens.end();
  50. I != E; ++I) {
  51. const UnwrappedLineNode &Node = *I;
  52. Current->Next = I->Tok;
  53. I->Tok->Previous = Current;
  54. Current = Current->Next;
  55. Current->Children.clear();
  56. for (const auto &Child : Node.Children) {
  57. Children.push_back(new AnnotatedLine(Child));
  58. Current->Children.push_back(Children.back());
  59. }
  60. }
  61. Last = Current;
  62. Last->Next = nullptr;
  63. }
  64. ~AnnotatedLine() {
  65. for (unsigned i = 0, e = Children.size(); i != e; ++i) {
  66. delete Children[i];
  67. }
  68. FormatToken *Current = First;
  69. while (Current) {
  70. Current->Children.clear();
  71. Current->Role.reset();
  72. Current = Current->Next;
  73. }
  74. }
  75. /// \c true if this line starts with the given tokens in order, ignoring
  76. /// comments.
  77. template <typename... Ts> bool startsWith(Ts... Tokens) const {
  78. return First && First->startsSequence(Tokens...);
  79. }
  80. /// \c true if this line ends with the given tokens in reversed order,
  81. /// ignoring comments.
  82. /// For example, given tokens [T1, T2, T3, ...], the function returns true if
  83. /// this line is like "... T3 T2 T1".
  84. template <typename... Ts> bool endsWith(Ts... Tokens) const {
  85. return Last && Last->endsSequence(Tokens...);
  86. }
  87. /// \c true if this line looks like a function definition instead of a
  88. /// function declaration. Asserts MightBeFunctionDecl.
  89. bool mightBeFunctionDefinition() const {
  90. assert(MightBeFunctionDecl);
  91. // Try to determine if the end of a stream of tokens is either the
  92. // Definition or the Declaration for a function. It does this by looking for
  93. // the ';' in foo(); and using that it ends with a ; to know this is the
  94. // Definition, however the line could end with
  95. // foo(); /* comment */
  96. // or
  97. // foo(); // comment
  98. // or
  99. // foo() // comment
  100. // endsWith() ignores the comment.
  101. return !endsWith(tok::semi);
  102. }
  103. /// \c true if this line starts a namespace definition.
  104. bool startsWithNamespace() const {
  105. return startsWith(tok::kw_namespace) || startsWith(TT_NamespaceMacro) ||
  106. startsWith(tok::kw_inline, tok::kw_namespace) ||
  107. startsWith(tok::kw_export, tok::kw_namespace);
  108. }
  109. FormatToken *First;
  110. FormatToken *Last;
  111. SmallVector<AnnotatedLine *, 0> Children;
  112. LineType Type;
  113. unsigned Level;
  114. size_t MatchingOpeningBlockLineIndex;
  115. size_t MatchingClosingBlockLineIndex;
  116. bool InPPDirective;
  117. bool MustBeDeclaration;
  118. bool MightBeFunctionDecl;
  119. bool IsMultiVariableDeclStmt;
  120. /// \c True if this line should be formatted, i.e. intersects directly or
  121. /// indirectly with one of the input ranges.
  122. bool Affected;
  123. /// \c True if the leading empty lines of this line intersect with one of the
  124. /// input ranges.
  125. bool LeadingEmptyLinesAffected;
  126. /// \c True if one of this line's children intersects with an input range.
  127. bool ChildrenAffected;
  128. unsigned FirstStartColumn;
  129. private:
  130. // Disallow copying.
  131. AnnotatedLine(const AnnotatedLine &) = delete;
  132. void operator=(const AnnotatedLine &) = delete;
  133. };
  134. /// Determines extra information about the tokens comprising an
  135. /// \c UnwrappedLine.
  136. class TokenAnnotator {
  137. public:
  138. TokenAnnotator(const FormatStyle &Style, const AdditionalKeywords &Keywords)
  139. : Style(Style), Keywords(Keywords) {}
  140. /// Adapts the indent levels of comment lines to the indent of the
  141. /// subsequent line.
  142. // FIXME: Can/should this be done in the UnwrappedLineParser?
  143. void setCommentLineLevels(SmallVectorImpl<AnnotatedLine *> &Lines);
  144. void annotate(AnnotatedLine &Line);
  145. void calculateFormattingInformation(AnnotatedLine &Line);
  146. private:
  147. /// Calculate the penalty for splitting before \c Tok.
  148. unsigned splitPenalty(const AnnotatedLine &Line, const FormatToken &Tok,
  149. bool InFunctionDecl);
  150. bool spaceRequiredBeforeParens(const FormatToken &Right) const;
  151. bool spaceRequiredBetween(const AnnotatedLine &Line, const FormatToken &Left,
  152. const FormatToken &Right);
  153. bool spaceRequiredBefore(const AnnotatedLine &Line, const FormatToken &Right);
  154. bool mustBreakBefore(const AnnotatedLine &Line, const FormatToken &Right);
  155. bool canBreakBefore(const AnnotatedLine &Line, const FormatToken &Right);
  156. bool mustBreakForReturnType(const AnnotatedLine &Line) const;
  157. void printDebugInfo(const AnnotatedLine &Line);
  158. void calculateUnbreakableTailLengths(AnnotatedLine &Line);
  159. const FormatStyle &Style;
  160. const AdditionalKeywords &Keywords;
  161. };
  162. } // end namespace format
  163. } // end namespace clang
  164. #endif