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