Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/clang/lib/Format/AffectedRangeManager.cpp
Line
Count
Source (jump to first uncovered line)
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
22
bool AffectedRangeManager::computeAffectedLines(
23
1.25M
    SmallVectorImpl<AnnotatedLine *> &Lines) {
24
1.25M
  SmallVectorImpl<AnnotatedLine *>::iterator I = Lines.begin();
25
1.25M
  SmallVectorImpl<AnnotatedLine *>::iterator E = Lines.end();
26
1.25M
  bool SomeLineAffected = false;
27
1.25M
  const AnnotatedLine *PreviousLine = nullptr;
28
2.75M
  while (I != E) {
29
1.50M
    AnnotatedLine *Line = *I;
30
1.50M
    assert(Line->First);
31
0
    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
1.50M
    if (Line->InPPDirective) {
36
253k
      FormatToken *Last = Line->Last;
37
253k
      SmallVectorImpl<AnnotatedLine *>::iterator PPEnd = I + 1;
38
269k
      while (PPEnd != E && !(*PPEnd)->First->HasUnescapedNewline) {
39
15.7k
        Last = (*PPEnd)->Last;
40
15.7k
        ++PPEnd;
41
15.7k
      }
42
43
253k
      if (affectsTokenRange(*Line->First, *Last,
44
253k
                            /*IncludeLeadingNewlines=*/false)) {
45
253k
        SomeLineAffected = true;
46
253k
        markAllAsAffected(I, PPEnd);
47
253k
      }
48
253k
      I = PPEnd;
49
253k
      continue;
50
253k
    }
51
52
1.24M
    if (nonPPLineAffected(Line, PreviousLine, Lines))
53
1.24M
      SomeLineAffected = true;
54
55
1.24M
    PreviousLine = Line;
56
1.24M
    ++I;
57
1.24M
  }
58
1.25M
  return SomeLineAffected;
59
1.25M
}
60
61
bool AffectedRangeManager::affectsCharSourceRange(
62
50.8M
    const CharSourceRange &Range) {
63
50.8M
  for (const CharSourceRange &R : Ranges) {
64
50.8M
    if (!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), R.getBegin()) &&
65
50.8M
        !SourceMgr.isBeforeInTranslationUnit(R.getEnd(), Range.getBegin())) {
66
50.8M
      return true;
67
50.8M
    }
68
50.8M
  }
69
0
  return false;
70
50.8M
}
71
72
bool AffectedRangeManager::affectsTokenRange(const FormatToken &First,
73
                                             const FormatToken &Last,
74
49.3M
                                             bool IncludeLeadingNewlines) {
75
49.3M
  SourceLocation Start = First.WhitespaceRange.getBegin();
76
49.3M
  if (!IncludeLeadingNewlines)
77
1.50M
    Start = Start.getLocWithOffset(First.LastNewlineOffset);
78
49.3M
  SourceLocation End = Last.getStartOfNonWhitespace();
79
49.3M
  End = End.getLocWithOffset(Last.TokenText.size());
80
49.3M
  CharSourceRange Range = CharSourceRange::getCharRange(Start, End);
81
49.3M
  return affectsCharSourceRange(Range);
82
49.3M
}
83
84
1.50M
bool AffectedRangeManager::affectsLeadingEmptyLines(const FormatToken &Tok) {
85
1.50M
  CharSourceRange EmptyLineRange = CharSourceRange::getCharRange(
86
1.50M
      Tok.WhitespaceRange.getBegin(),
87
1.50M
      Tok.WhitespaceRange.getBegin().getLocWithOffset(Tok.LastNewlineOffset));
88
1.50M
  return affectsCharSourceRange(EmptyLineRange);
89
1.50M
}
90
91
void AffectedRangeManager::markAllAsAffected(
92
    SmallVectorImpl<AnnotatedLine *>::iterator I,
93
597k
    SmallVectorImpl<AnnotatedLine *>::iterator E) {
94
942k
  while (I != E) {
95
344k
    (*I)->Affected = true;
96
344k
    markAllAsAffected((*I)->Children.begin(), (*I)->Children.end());
97
344k
    ++I;
98
344k
  }
99
597k
}
100
101
bool AffectedRangeManager::nonPPLineAffected(
102
    AnnotatedLine *Line, const AnnotatedLine *PreviousLine,
103
1.24M
    SmallVectorImpl<AnnotatedLine *> &Lines) {
104
1.24M
  bool SomeLineAffected = false;
105
1.24M
  Line->ChildrenAffected = computeAffectedLines(Line->Children);
106
1.24M
  if (Line->ChildrenAffected)
107
11.3k
    SomeLineAffected = true;
108
109
  // Stores whether one of the line's tokens is directly affected.
110
1.24M
  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
1.24M
  bool IncludeLeadingNewlines = false;
114
115
  // Stores whether the first child line of any of this line's tokens is
116
  // affected.
117
1.24M
  bool SomeFirstChildAffected = false;
118
119
1.24M
  assert(Line->First);
120
50.3M
  for (FormatToken *Tok = Line->First; Tok; Tok = Tok->Next) {
121
    // Determine whether 'Tok' was affected.
122
49.1M
    if (affectsTokenRange(*Tok, *Tok, IncludeLeadingNewlines))
123
49.1M
      SomeTokenAffected = true;
124
125
    // Determine whether the first child of 'Tok' was affected.
126
49.1M
    if (!Tok->Children.empty() && Tok->Children.front()->Affected)
127
13.4k
      SomeFirstChildAffected = true;
128
129
49.1M
    IncludeLeadingNewlines = Tok->Children.empty();
130
49.1M
  }
131
132
  // Was this line moved, i.e. has it previously been on the same line as an
133
  // affected line?
134
1.24M
  bool LineMoved = PreviousLine && PreviousLine->Affected &&
135
1.24M
                   Line->First->NewlinesBefore == 0;
136
137
1.24M
  bool IsContinuedComment =
138
1.24M
      Line->First->is(tok::comment) && !Line->First->Next &&
139
1.24M
      Line->First->NewlinesBefore < 2 && PreviousLine &&
140
1.24M
      PreviousLine->Affected && PreviousLine->Last->is(tok::comment);
141
142
1.24M
  bool IsAffectedClosingBrace =
143
1.24M
      Line->First->is(tok::r_brace) &&
144
1.24M
      Line->MatchingOpeningBlockLineIndex != UnwrappedLine::kInvalidIndex &&
145
1.24M
      Lines[Line->MatchingOpeningBlockLineIndex]->Affected;
146
147
1.24M
  if (SomeTokenAffected || SomeFirstChildAffected || LineMoved ||
148
1.24M
      IsContinuedComment || IsAffectedClosingBrace) {
149
1.24M
    Line->Affected = true;
150
1.24M
    SomeLineAffected = true;
151
1.24M
  }
152
1.24M
  return SomeLineAffected;
153
1.24M
}
154
155
} // namespace format
156
} // namespace clang