clang API Documentation

TokenAnnotator.h
Go to the documentation of this file.
00001 //===--- TokenAnnotator.h - Format C++ code ---------------------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 ///
00010 /// \file
00011 /// \brief This file implements a token annotator, i.e. creates
00012 /// \c AnnotatedTokens out of \c FormatTokens with required extra information.
00013 ///
00014 //===----------------------------------------------------------------------===//
00015 
00016 #ifndef LLVM_CLANG_LIB_FORMAT_TOKENANNOTATOR_H
00017 #define LLVM_CLANG_LIB_FORMAT_TOKENANNOTATOR_H
00018 
00019 #include "UnwrappedLineParser.h"
00020 #include "clang/Format/Format.h"
00021 #include <string>
00022 
00023 namespace clang {
00024 class SourceManager;
00025 
00026 namespace format {
00027 
00028 enum LineType {
00029   LT_Invalid,
00030   LT_Other,
00031   LT_PreprocessorDirective,
00032   LT_VirtualFunctionDecl,
00033   LT_ObjCDecl, // An @interface, @implementation, or @protocol line.
00034   LT_ObjCMethodDecl,
00035   LT_ObjCProperty // An @property line.
00036 };
00037 
00038 class AnnotatedLine {
00039 public:
00040   AnnotatedLine(const UnwrappedLine &Line)
00041       : First(Line.Tokens.front().Tok), Level(Line.Level),
00042         InPPDirective(Line.InPPDirective),
00043         MustBeDeclaration(Line.MustBeDeclaration), MightBeFunctionDecl(false),
00044         Affected(false), LeadingEmptyLinesAffected(false),
00045         ChildrenAffected(false) {
00046     assert(!Line.Tokens.empty());
00047 
00048     // Calculate Next and Previous for all tokens. Note that we must overwrite
00049     // Next and Previous for every token, as previous formatting runs might have
00050     // left them in a different state.
00051     First->Previous = nullptr;
00052     FormatToken *Current = First;
00053     for (std::list<UnwrappedLineNode>::const_iterator I = ++Line.Tokens.begin(),
00054                                                       E = Line.Tokens.end();
00055          I != E; ++I) {
00056       const UnwrappedLineNode &Node = *I;
00057       Current->Next = I->Tok;
00058       I->Tok->Previous = Current;
00059       Current = Current->Next;
00060       Current->Children.clear();
00061       for (SmallVectorImpl<UnwrappedLine>::const_iterator
00062                I = Node.Children.begin(),
00063                E = Node.Children.end();
00064            I != E; ++I) {
00065         Children.push_back(new AnnotatedLine(*I));
00066         Current->Children.push_back(Children.back());
00067       }
00068     }
00069     Last = Current;
00070     Last->Next = nullptr;
00071   }
00072 
00073   ~AnnotatedLine() {
00074     for (unsigned i = 0, e = Children.size(); i != e; ++i) {
00075       delete Children[i];
00076     }
00077   }
00078 
00079   FormatToken *First;
00080   FormatToken *Last;
00081 
00082   SmallVector<AnnotatedLine *, 0> Children;
00083 
00084   LineType Type;
00085   unsigned Level;
00086   bool InPPDirective;
00087   bool MustBeDeclaration;
00088   bool MightBeFunctionDecl;
00089 
00090   /// \c True if this line should be formatted, i.e. intersects directly or
00091   /// indirectly with one of the input ranges.
00092   bool Affected;
00093 
00094   /// \c True if the leading empty lines of this line intersect with one of the
00095   /// input ranges.
00096   bool LeadingEmptyLinesAffected;
00097 
00098   /// \c True if a one of this line's children intersects with an input range.
00099   bool ChildrenAffected;
00100 
00101 private:
00102   // Disallow copying.
00103   AnnotatedLine(const AnnotatedLine &) LLVM_DELETED_FUNCTION;
00104   void operator=(const AnnotatedLine &) LLVM_DELETED_FUNCTION;
00105 };
00106 
00107 /// \brief Determines extra information about the tokens comprising an
00108 /// \c UnwrappedLine.
00109 class TokenAnnotator {
00110 public:
00111   TokenAnnotator(const FormatStyle &Style, const AdditionalKeywords &Keywords)
00112       : Style(Style), Keywords(Keywords) {}
00113 
00114   /// \brief Adapts the indent levels of comment lines to the indent of the
00115   /// subsequent line.
00116   // FIXME: Can/should this be done in the UnwrappedLineParser?
00117   void setCommentLineLevels(SmallVectorImpl<AnnotatedLine *> &Lines);
00118 
00119   void annotate(AnnotatedLine &Line);
00120   void calculateFormattingInformation(AnnotatedLine &Line);
00121 
00122 private:
00123   /// \brief Calculate the penalty for splitting before \c Tok.
00124   unsigned splitPenalty(const AnnotatedLine &Line, const FormatToken &Tok,
00125                         bool InFunctionDecl);
00126 
00127   bool spaceRequiredBetween(const AnnotatedLine &Line, const FormatToken &Left,
00128                             const FormatToken &Right);
00129 
00130   bool spaceRequiredBefore(const AnnotatedLine &Line, const FormatToken &Tok);
00131 
00132   bool mustBreakBefore(const AnnotatedLine &Line, const FormatToken &Right);
00133 
00134   bool canBreakBefore(const AnnotatedLine &Line, const FormatToken &Right);
00135 
00136   void printDebugInfo(const AnnotatedLine &Line);
00137 
00138   void calculateUnbreakableTailLengths(AnnotatedLine &Line);
00139 
00140   const FormatStyle &Style;
00141 
00142   const AdditionalKeywords &Keywords;
00143 };
00144 
00145 } // end namespace format
00146 } // end namespace clang
00147 
00148 #endif