clang  6.0.0svn
AffectedRangeManager.cpp
Go to the documentation of this file.
1 //===--- AffectedRangeManager.cpp - Format C++ code -----------------------===//
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 AffectRangeManager class.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #include "AffectedRangeManager.h"
16 
17 #include "FormatToken.h"
18 #include "TokenAnnotator.h"
19 
20 namespace clang {
21 namespace format {
22 
26  bool SomeLineAffected = false;
27  const AnnotatedLine *PreviousLine = nullptr;
28  while (I != E) {
29  AnnotatedLine *Line = *I;
30  Line->LeadingEmptyLinesAffected = affectsLeadingEmptyLines(*Line->First);
31 
32  // If a line is part of a preprocessor directive, it needs to be formatted
33  // if any token within the directive is affected.
34  if (Line->InPPDirective) {
35  FormatToken *Last = Line->Last;
37  while (PPEnd != E && !(*PPEnd)->First->HasUnescapedNewline) {
38  Last = (*PPEnd)->Last;
39  ++PPEnd;
40  }
41 
42  if (affectsTokenRange(*Line->First, *Last,
43  /*IncludeLeadingNewlines=*/false)) {
44  SomeLineAffected = true;
45  markAllAsAffected(I, PPEnd);
46  }
47  I = PPEnd;
48  continue;
49  }
50 
51  if (nonPPLineAffected(Line, PreviousLine))
52  SomeLineAffected = true;
53 
54  PreviousLine = Line;
55  ++I;
56  }
57  return SomeLineAffected;
58 }
59 
61  const CharSourceRange &Range) {
63  E = Ranges.end();
64  I != E; ++I) {
65  if (!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), I->getBegin()) &&
66  !SourceMgr.isBeforeInTranslationUnit(I->getEnd(), Range.getBegin()))
67  return true;
68  }
69  return false;
70 }
71 
72 bool AffectedRangeManager::affectsTokenRange(const FormatToken &First,
73  const FormatToken &Last,
74  bool IncludeLeadingNewlines) {
75  SourceLocation Start = First.WhitespaceRange.getBegin();
76  if (!IncludeLeadingNewlines)
77  Start = Start.getLocWithOffset(First.LastNewlineOffset);
79  End = End.getLocWithOffset(Last.TokenText.size());
81  return affectsCharSourceRange(Range);
82 }
83 
84 bool AffectedRangeManager::affectsLeadingEmptyLines(const FormatToken &Tok) {
88  return affectsCharSourceRange(EmptyLineRange);
89 }
90 
91 void AffectedRangeManager::markAllAsAffected(
94  while (I != E) {
95  (*I)->Affected = true;
96  markAllAsAffected((*I)->Children.begin(), (*I)->Children.end());
97  ++I;
98  }
99 }
100 
101 bool AffectedRangeManager::nonPPLineAffected(
102  AnnotatedLine *Line, const AnnotatedLine *PreviousLine) {
103  bool SomeLineAffected = false;
104  Line->ChildrenAffected =
105  computeAffectedLines(Line->Children.begin(), Line->Children.end());
106  if (Line->ChildrenAffected)
107  SomeLineAffected = true;
108 
109  // Stores whether one of the line's tokens is directly affected.
110  bool SomeTokenAffected = false;
111  // Stores whether we need to look at the leading newlines of the next token
112  // in order to determine whether it was affected.
113  bool IncludeLeadingNewlines = false;
114 
115  // Stores whether the first child line of any of this line's tokens is
116  // affected.
117  bool SomeFirstChildAffected = false;
118 
119  for (FormatToken *Tok = Line->First; Tok; Tok = Tok->Next) {
120  // Determine whether 'Tok' was affected.
121  if (affectsTokenRange(*Tok, *Tok, IncludeLeadingNewlines))
122  SomeTokenAffected = true;
123 
124  // Determine whether the first child of 'Tok' was affected.
125  if (!Tok->Children.empty() && Tok->Children.front()->Affected)
126  SomeFirstChildAffected = true;
127 
128  IncludeLeadingNewlines = Tok->Children.empty();
129  }
130 
131  // Was this line moved, i.e. has it previously been on the same line as an
132  // affected line?
133  bool LineMoved = PreviousLine && PreviousLine->Affected &&
134  Line->First->NewlinesBefore == 0;
135 
136  bool IsContinuedComment =
137  Line->First->is(tok::comment) && Line->First->Next == nullptr &&
138  Line->First->NewlinesBefore < 2 && PreviousLine &&
139  PreviousLine->Affected && PreviousLine->Last->is(tok::comment);
140 
141  if (SomeTokenAffected || SomeFirstChildAffected || LineMoved ||
142  IsContinuedComment) {
143  Line->Affected = true;
144  SomeLineAffected = true;
145  }
146  return SomeLineAffected;
147 }
148 
149 } // namespace format
150 } // namespace clang
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
AffectedRangeManager class manages affected ranges in the code.
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
bool computeAffectedLines(SmallVectorImpl< AnnotatedLine *>::iterator I, SmallVectorImpl< AnnotatedLine *>::iterator E)
bool LeadingEmptyLinesAffected
True if the leading empty lines of this line intersect with one of the input ranges.
unsigned NewlinesBefore
The number of newlines immediately before the Token.
Definition: FormatToken.h:130
FormatToken * Next
The next token in the unwrapped line.
Definition: FormatToken.h:283
SourceLocation getBegin() const
This file implements a token annotator, i.e.
const FormatToken & Tok
bool ChildrenAffected
True if one of this line&#39;s children intersects with an input range.
SourceLocation getStartOfNonWhitespace() const
Returns actual token start location without leading escaped newlines and whitespace.
Definition: FormatToken.h:439
SourceLocation End
Represents a character-granular source range.
const AnnotatedLine * Line
SmallVector< AnnotatedLine *, 0 > Children
A wrapper around a Token storing information about the whitespace characters preceding it...
Definition: FormatToken.h:120
bool Affected
True if this line should be formatted, i.e.
static CharSourceRange getCharRange(SourceRange R)
unsigned LastNewlineOffset
The offset just past the last &#39; &#39; in this token&#39;s leading whitespace (relative to WhiteSpaceStart)...
Definition: FormatToken.h:141
Encodes a location in the source.
bool is(tok::TokenKind Kind) const
Definition: FormatToken.h:297
SourceRange WhitespaceRange
The range of the whitespace immediately preceding the Token.
Definition: FormatToken.h:137
StringRef TokenText
The raw text of the token.
Definition: FormatToken.h:168
Dataflow Directional Tag Classes.
bool affectsCharSourceRange(const CharSourceRange &Range)
SourceLocation getEnd() const
SmallVector< AnnotatedLine *, 1 > Children
If this token starts a block, this contains all the unwrapped lines in it.
Definition: FormatToken.h:287
This file contains the declaration of the FormatToken, a wrapper around Token with additional informa...
SourceLocation getBegin() const