brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.3 KiB · 67108f3 Raw
157 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// This file implements AffectRangeManager class.11///12//===----------------------------------------------------------------------===//13 14#include "AffectedRangeManager.h"15 16#include "FormatToken.h"17#include "TokenAnnotator.h"18 19namespace clang {20namespace format {21 22bool AffectedRangeManager::computeAffectedLines(23    SmallVectorImpl<AnnotatedLine *> &Lines) {24  ArrayRef<AnnotatedLine *>::iterator I = Lines.begin();25  ArrayRef<AnnotatedLine *>::iterator E = Lines.end();26  bool SomeLineAffected = false;27  const AnnotatedLine *PreviousLine = nullptr;28  while (I != E) {29    AnnotatedLine *Line = *I;30    assert(Line->First);31    Line->LeadingEmptyLinesAffected = affectsLeadingEmptyLines(*Line->First);32 33    // If a line is part of a preprocessor directive, it needs to be formatted34    // if any token within the directive is affected.35    if (Line->InPPDirective) {36      FormatToken *Last = Line->Last;37      const auto *PPEnd = I + 1;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 61bool AffectedRangeManager::affectsCharSourceRange(62    const CharSourceRange &Range) {63  for (const CharSourceRange &R : Ranges) {64    if (!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), R.getBegin()) &&65        !SourceMgr.isBeforeInTranslationUnit(R.getEnd(), Range.getBegin())) {66      return true;67    }68  }69  return false;70}71 72bool 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);78  SourceLocation End = Last.getStartOfNonWhitespace();79  End = End.getLocWithOffset(Last.TokenText.size());80  CharSourceRange Range = CharSourceRange::getCharRange(Start, End);81  return affectsCharSourceRange(Range);82}83 84bool AffectedRangeManager::affectsLeadingEmptyLines(const FormatToken &Tok) {85  CharSourceRange EmptyLineRange = CharSourceRange::getCharRange(86      Tok.WhitespaceRange.getBegin(),87      Tok.WhitespaceRange.getBegin().getLocWithOffset(Tok.LastNewlineOffset));88  return affectsCharSourceRange(EmptyLineRange);89}90 91void AffectedRangeManager::markAllAsAffected(92    ArrayRef<AnnotatedLine *>::iterator I,93    ArrayRef<AnnotatedLine *>::iterator E) {94  while (I != E) {95    (*I)->Affected = true;96    markAllAsAffected((*I)->Children.begin(), (*I)->Children.end());97    ++I;98  }99}100 101bool AffectedRangeManager::nonPPLineAffected(102    AnnotatedLine *Line, const AnnotatedLine *PreviousLine,103    SmallVectorImpl<AnnotatedLine *> &Lines) {104  bool SomeLineAffected = false;105  Line->ChildrenAffected = computeAffectedLines(Line->Children);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 token112  // 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 is116  // affected.117  bool SomeFirstChildAffected = false;118 119  assert(Line->First);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 an133  // 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 &&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) &&144      Line->MatchingOpeningBlockLineIndex != UnwrappedLine::kInvalidIndex &&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 format156} // namespace clang157