clang  9.0.0svn
AffectedRangeManager.cpp
Go to the documentation of this file.
1 //===--- AffectedRangeManager.cpp - Format C++ code -----------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// This file implements AffectRangeManager class.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #include "AffectedRangeManager.h"
15 
16 #include "FormatToken.h"
17 #include "TokenAnnotator.h"
18 
19 namespace clang {
20 namespace format {
21 
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, Lines))
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,
104  bool SomeLineAffected = false;
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  bool IsAffectedClosingBrace =
142  Line->First->is(tok::r_brace) &&
144  Lines[Line->MatchingOpeningBlockLineIndex]->Affected;
145 
146  if (SomeTokenAffected || SomeFirstChildAffected || LineMoved ||
147  IsContinuedComment || IsAffectedClosingBrace) {
148  Line->Affected = true;
149  SomeLineAffected = true;
150  }
151  return SomeLineAffected;
152 }
153 
154 } // namespace format
155 } // 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:292
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:462
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:306
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:296
This file contains the declaration of the FormatToken, a wrapper around Token with additional informa...
SourceLocation getBegin() const