clang  8.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 /// 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 
27  bool SomeLineAffected = false;
28  const AnnotatedLine *PreviousLine = nullptr;
29  while (I != E) {
30  AnnotatedLine *Line = *I;
31  Line->LeadingEmptyLinesAffected = affectsLeadingEmptyLines(*Line->First);
32 
33  // If a line is part of a preprocessor directive, it needs to be formatted
34  // if any token within the directive is affected.
35  if (Line->InPPDirective) {
36  FormatToken *Last = Line->Last;
38  while (PPEnd != E && !(*PPEnd)->First->HasUnescapedNewline) {
39  Last = (*PPEnd)->Last;
40  ++PPEnd;
41  }
42 
43  if (affectsTokenRange(*Line->First, *Last,
44  /*IncludeLeadingNewlines=*/false)) {
45  SomeLineAffected = true;
46  markAllAsAffected(I, PPEnd);
47  }
48  I = PPEnd;
49  continue;
50  }
51 
52  if (nonPPLineAffected(Line, PreviousLine, Lines))
53  SomeLineAffected = true;
54 
55  PreviousLine = Line;
56  ++I;
57  }
58  return SomeLineAffected;
59 }
60 
62  const CharSourceRange &Range) {
64  E = Ranges.end();
65  I != E; ++I) {
66  if (!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), I->getBegin()) &&
67  !SourceMgr.isBeforeInTranslationUnit(I->getEnd(), Range.getBegin()))
68  return true;
69  }
70  return false;
71 }
72 
73 bool AffectedRangeManager::affectsTokenRange(const FormatToken &First,
74  const FormatToken &Last,
75  bool IncludeLeadingNewlines) {
76  SourceLocation Start = First.WhitespaceRange.getBegin();
77  if (!IncludeLeadingNewlines)
78  Start = Start.getLocWithOffset(First.LastNewlineOffset);
80  End = End.getLocWithOffset(Last.TokenText.size());
82  return affectsCharSourceRange(Range);
83 }
84 
85 bool AffectedRangeManager::affectsLeadingEmptyLines(const FormatToken &Tok) {
89  return affectsCharSourceRange(EmptyLineRange);
90 }
91 
92 void AffectedRangeManager::markAllAsAffected(
95  while (I != E) {
96  (*I)->Affected = true;
97  markAllAsAffected((*I)->Children.begin(), (*I)->Children.end());
98  ++I;
99  }
100 }
101 
102 bool AffectedRangeManager::nonPPLineAffected(
103  AnnotatedLine *Line, const AnnotatedLine *PreviousLine,
105  bool SomeLineAffected = false;
107  if (Line->ChildrenAffected)
108  SomeLineAffected = true;
109 
110  // Stores whether one of the line's tokens is directly affected.
111  bool SomeTokenAffected = false;
112  // Stores whether we need to look at the leading newlines of the next token
113  // in order to determine whether it was affected.
114  bool IncludeLeadingNewlines = false;
115 
116  // Stores whether the first child line of any of this line's tokens is
117  // affected.
118  bool SomeFirstChildAffected = false;
119 
120  for (FormatToken *Tok = Line->First; Tok; Tok = Tok->Next) {
121  // Determine whether 'Tok' was affected.
122  if (affectsTokenRange(*Tok, *Tok, IncludeLeadingNewlines))
123  SomeTokenAffected = true;
124 
125  // Determine whether the first child of 'Tok' was affected.
126  if (!Tok->Children.empty() && Tok->Children.front()->Affected)
127  SomeFirstChildAffected = true;
128 
129  IncludeLeadingNewlines = Tok->Children.empty();
130  }
131 
132  // Was this line moved, i.e. has it previously been on the same line as an
133  // affected line?
134  bool LineMoved = PreviousLine && PreviousLine->Affected &&
135  Line->First->NewlinesBefore == 0;
136 
137  bool IsContinuedComment =
138  Line->First->is(tok::comment) && Line->First->Next == nullptr &&
139  Line->First->NewlinesBefore < 2 && PreviousLine &&
140  PreviousLine->Affected && PreviousLine->Last->is(tok::comment);
141 
142  bool IsAffectedClosingBrace =
143  Line->First->is(tok::r_brace) &&
145  Lines[Line->MatchingOpeningBlockLineIndex]->Affected;
146 
147  if (SomeTokenAffected || SomeFirstChildAffected || LineMoved ||
148  IsContinuedComment || IsAffectedClosingBrace) {
149  Line->Affected = true;
150  SomeLineAffected = true;
151  }
152  return SomeLineAffected;
153 }
154 
155 } // namespace format
156 } // 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 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:133
FormatToken * Next
The next token in the unwrapped line.
Definition: FormatToken.h:296
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:458
SourceLocation End
Represents a character-granular source range.
const AnnotatedLine * Line
SmallVector< AnnotatedLine *, 0 > Children
static const size_t kInvalidIndex
A wrapper around a Token storing information about the whitespace characters preceding it...
Definition: FormatToken.h:123
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:144
Encodes a location in the source.
bool is(tok::TokenKind Kind) const
Definition: FormatToken.h:310
SourceRange WhitespaceRange
The range of the whitespace immediately preceding the Token.
Definition: FormatToken.h:140
StringRef TokenText
The raw text of the token.
Definition: FormatToken.h:171
bool computeAffectedLines(SmallVectorImpl< AnnotatedLine *> &Lines)
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:300
This file contains the declaration of the FormatToken, a wrapper around Token with additional informa...
SourceLocation getBegin() const