1249261Sdim//===--- TokenAnnotator.h - Format C++ code ---------------------*- C++ -*-===//
2249261Sdim//
3249261Sdim//                     The LLVM Compiler Infrastructure
4249261Sdim//
5249261Sdim// This file is distributed under the University of Illinois Open Source
6249261Sdim// License. See LICENSE.TXT for details.
7249261Sdim//
8249261Sdim//===----------------------------------------------------------------------===//
9249261Sdim///
10249261Sdim/// \file
11249261Sdim/// \brief This file implements a token annotator, i.e. creates
12249261Sdim/// \c AnnotatedTokens out of \c FormatTokens with required extra information.
13249261Sdim///
14249261Sdim//===----------------------------------------------------------------------===//
15249261Sdim
16249261Sdim#ifndef LLVM_CLANG_FORMAT_TOKEN_ANNOTATOR_H
17249261Sdim#define LLVM_CLANG_FORMAT_TOKEN_ANNOTATOR_H
18249261Sdim
19249261Sdim#include "UnwrappedLineParser.h"
20249261Sdim#include "clang/Format/Format.h"
21249261Sdim#include <string>
22249261Sdim
23249261Sdimnamespace clang {
24249261Sdimclass SourceManager;
25249261Sdim
26249261Sdimnamespace format {
27249261Sdim
28249261Sdimenum LineType {
29249261Sdim  LT_Invalid,
30249261Sdim  LT_Other,
31249261Sdim  LT_PreprocessorDirective,
32249261Sdim  LT_VirtualFunctionDecl,
33249261Sdim  LT_ObjCDecl, // An @interface, @implementation, or @protocol line.
34249261Sdim  LT_ObjCMethodDecl,
35249261Sdim  LT_ObjCProperty // An @property line.
36249261Sdim};
37249261Sdim
38249261Sdimclass AnnotatedLine {
39249261Sdimpublic:
40249261Sdim  AnnotatedLine(const UnwrappedLine &Line)
41263509Sdim      : First(Line.Tokens.front().Tok), Level(Line.Level),
42249261Sdim        InPPDirective(Line.InPPDirective),
43252723Sdim        MustBeDeclaration(Line.MustBeDeclaration), MightBeFunctionDecl(false),
44252723Sdim        StartsDefinition(false) {
45249261Sdim    assert(!Line.Tokens.empty());
46263509Sdim
47263509Sdim    // Calculate Next and Previous for all tokens. Note that we must overwrite
48263509Sdim    // Next and Previous for every token, as previous formatting runs might have
49263509Sdim    // left them in a different state.
50263509Sdim    First->Previous = NULL;
51263509Sdim    FormatToken *Current = First;
52263509Sdim    for (std::list<UnwrappedLineNode>::const_iterator I = ++Line.Tokens.begin(),
53263509Sdim                                                      E = Line.Tokens.end();
54249261Sdim         I != E; ++I) {
55263509Sdim      const UnwrappedLineNode &Node = *I;
56263509Sdim      Current->Next = I->Tok;
57263509Sdim      I->Tok->Previous = Current;
58263509Sdim      Current = Current->Next;
59263509Sdim      Current->Children.clear();
60263509Sdim      for (SmallVectorImpl<UnwrappedLine>::const_iterator
61263509Sdim               I = Node.Children.begin(),
62263509Sdim               E = Node.Children.end();
63263509Sdim           I != E; ++I) {
64263509Sdim        Children.push_back(new AnnotatedLine(*I));
65263509Sdim        Current->Children.push_back(Children.back());
66263509Sdim      }
67249261Sdim    }
68249261Sdim    Last = Current;
69263509Sdim    Last->Next = NULL;
70249261Sdim  }
71263509Sdim
72263509Sdim  ~AnnotatedLine() {
73263509Sdim    for (unsigned i = 0, e = Children.size(); i != e; ++i) {
74263509Sdim      delete Children[i];
75249261Sdim    }
76249261Sdim  }
77249261Sdim
78263509Sdim  FormatToken *First;
79263509Sdim  FormatToken *Last;
80249261Sdim
81263509Sdim  SmallVector<AnnotatedLine *, 0> Children;
82263509Sdim
83249261Sdim  LineType Type;
84249261Sdim  unsigned Level;
85249261Sdim  bool InPPDirective;
86249261Sdim  bool MustBeDeclaration;
87249261Sdim  bool MightBeFunctionDecl;
88252723Sdim  bool StartsDefinition;
89263509Sdim
90263509Sdimprivate:
91263509Sdim  // Disallow copying.
92263509Sdim  AnnotatedLine(const AnnotatedLine &) LLVM_DELETED_FUNCTION;
93263509Sdim  void operator=(const AnnotatedLine &) LLVM_DELETED_FUNCTION;
94249261Sdim};
95249261Sdim
96249261Sdim/// \brief Determines extra information about the tokens comprising an
97249261Sdim/// \c UnwrappedLine.
98249261Sdimclass TokenAnnotator {
99249261Sdimpublic:
100263509Sdim  TokenAnnotator(const FormatStyle &Style, IdentifierInfo &Ident_in)
101263509Sdim      : Style(Style), Ident_in(Ident_in) {}
102249261Sdim
103263509Sdim  /// \brief Adapts the indent levels of comment lines to the indent of the
104263509Sdim  /// subsequent line.
105263509Sdim  // FIXME: Can/should this be done in the UnwrappedLineParser?
106263509Sdim  void setCommentLineLevels(SmallVectorImpl<AnnotatedLine *> &Lines);
107263509Sdim
108249261Sdim  void annotate(AnnotatedLine &Line);
109249261Sdim  void calculateFormattingInformation(AnnotatedLine &Line);
110249261Sdim
111249261Sdimprivate:
112249261Sdim  /// \brief Calculate the penalty for splitting before \c Tok.
113263509Sdim  unsigned splitPenalty(const AnnotatedLine &Line, const FormatToken &Tok,
114263509Sdim                        bool InFunctionDecl);
115249261Sdim
116263509Sdim  bool spaceRequiredBetween(const AnnotatedLine &Line, const FormatToken &Left,
117263509Sdim                            const FormatToken &Right);
118249261Sdim
119263509Sdim  bool spaceRequiredBefore(const AnnotatedLine &Line, const FormatToken &Tok);
120249261Sdim
121263509Sdim  bool mustBreakBefore(const AnnotatedLine &Line, const FormatToken &Right);
122249261Sdim
123263509Sdim  bool canBreakBefore(const AnnotatedLine &Line, const FormatToken &Right);
124263509Sdim
125252723Sdim  void printDebugInfo(const AnnotatedLine &Line);
126252723Sdim
127263509Sdim  void calculateUnbreakableTailLengths(AnnotatedLine &Line);
128263509Sdim
129249261Sdim  const FormatStyle &Style;
130249261Sdim
131249261Sdim  // Contextual keywords:
132249261Sdim  IdentifierInfo &Ident_in;
133249261Sdim};
134249261Sdim
135249261Sdim} // end namespace format
136249261Sdim} // end namespace clang
137249261Sdim
138249261Sdim#endif // LLVM_CLANG_FORMAT_TOKEN_ANNOTATOR_H
139