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