xref: /aosp_15_r20/external/clang/lib/Format/TokenAnnotator.h (revision 67e74705e28f6214e480b399dd47ea732279e315)
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