//===--- AffectedRangeManager.cpp - Format C++ code -----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file implements AffectRangeManager class.
///
//===----------------------------------------------------------------------===//

#include "AffectedRangeManager.h"

#include "FormatToken.h"
#include "TokenAnnotator.h"

namespace clang {
namespace format {

bool AffectedRangeManager::computeAffectedLines(
    SmallVectorImpl<AnnotatedLine *> &Lines) {
  SmallVectorImpl<AnnotatedLine *>::iterator I = Lines.begin();
  SmallVectorImpl<AnnotatedLine *>::iterator E = Lines.end();
  bool SomeLineAffected = false;
  const AnnotatedLine *PreviousLine = nullptr;
  while (I != E) {
    AnnotatedLine *Line = *I;
    Line->LeadingEmptyLinesAffected = affectsLeadingEmptyLines(*Line->First);

    // If a line is part of a preprocessor directive, it needs to be formatted
    // if any token within the directive is affected.
    if (Line->InPPDirective) {
      FormatToken *Last = Line->Last;
      SmallVectorImpl<AnnotatedLine *>::iterator PPEnd = I + 1;
      while (PPEnd != E && !(*PPEnd)->First->HasUnescapedNewline) {
        Last = (*PPEnd)->Last;
        ++PPEnd;
      }

      if (affectsTokenRange(*Line->First, *Last,
                            /*IncludeLeadingNewlines=*/false)) {
        SomeLineAffected = true;
        markAllAsAffected(I, PPEnd);
      }
      I = PPEnd;
      continue;
    }

    if (nonPPLineAffected(Line, PreviousLine, Lines))
      SomeLineAffected = true;

    PreviousLine = Line;
    ++I;
  }
  return SomeLineAffected;
}

bool AffectedRangeManager::affectsCharSourceRange(
    const CharSourceRange &Range) {
  for (SmallVectorImpl<CharSourceRange>::const_iterator I = Ranges.begin(),
                                                        E = Ranges.end();
       I != E; ++I) {
    if (!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), I->getBegin()) &&
        !SourceMgr.isBeforeInTranslationUnit(I->getEnd(), Range.getBegin()))
      return true;
  }
  return false;
}

bool AffectedRangeManager::affectsTokenRange(const FormatToken &First,
                                             const FormatToken &Last,
                                             bool IncludeLeadingNewlines) {
  SourceLocation Start = First.WhitespaceRange.getBegin();
  if (!IncludeLeadingNewlines)
    Start = Start.getLocWithOffset(First.LastNewlineOffset);
  SourceLocation End = Last.getStartOfNonWhitespace();
  End = End.getLocWithOffset(Last.TokenText.size());
  CharSourceRange Range = CharSourceRange::getCharRange(Start, End);
  return affectsCharSourceRange(Range);
}

bool AffectedRangeManager::affectsLeadingEmptyLines(const FormatToken &Tok) {
  CharSourceRange EmptyLineRange = CharSourceRange::getCharRange(
      Tok.WhitespaceRange.getBegin(),
      Tok.WhitespaceRange.getBegin().getLocWithOffset(Tok.LastNewlineOffset));
  return affectsCharSourceRange(EmptyLineRange);
}

void AffectedRangeManager::markAllAsAffected(
    SmallVectorImpl<AnnotatedLine *>::iterator I,
    SmallVectorImpl<AnnotatedLine *>::iterator E) {
  while (I != E) {
    (*I)->Affected = true;
    markAllAsAffected((*I)->Children.begin(), (*I)->Children.end());
    ++I;
  }
}

bool AffectedRangeManager::nonPPLineAffected(
    AnnotatedLine *Line, const AnnotatedLine *PreviousLine,
    SmallVectorImpl<AnnotatedLine *> &Lines) {
  bool SomeLineAffected = false;
  Line->ChildrenAffected = computeAffectedLines(Line->Children);
  if (Line->ChildrenAffected)
    SomeLineAffected = true;

  // Stores whether one of the line's tokens is directly affected.
  bool SomeTokenAffected = false;
  // Stores whether we need to look at the leading newlines of the next token
  // in order to determine whether it was affected.
  bool IncludeLeadingNewlines = false;

  // Stores whether the first child line of any of this line's tokens is
  // affected.
  bool SomeFirstChildAffected = false;

  for (FormatToken *Tok = Line->First; Tok; Tok = Tok->Next) {
    // Determine whether 'Tok' was affected.
    if (affectsTokenRange(*Tok, *Tok, IncludeLeadingNewlines))
      SomeTokenAffected = true;

    // Determine whether the first child of 'Tok' was affected.
    if (!Tok->Children.empty() && Tok->Children.front()->Affected)
      SomeFirstChildAffected = true;

    IncludeLeadingNewlines = Tok->Children.empty();
  }

  // Was this line moved, i.e. has it previously been on the same line as an
  // affected line?
  bool LineMoved = PreviousLine && PreviousLine->Affected &&
                   Line->First->NewlinesBefore == 0;

  bool IsContinuedComment =
      Line->First->is(tok::comment) && Line->First->Next == nullptr &&
      Line->First->NewlinesBefore < 2 && PreviousLine &&
      PreviousLine->Affected && PreviousLine->Last->is(tok::comment);

  bool IsAffectedClosingBrace =
      Line->First->is(tok::r_brace) &&
      Line->MatchingOpeningBlockLineIndex != UnwrappedLine::kInvalidIndex &&
      Lines[Line->MatchingOpeningBlockLineIndex]->Affected;

  if (SomeTokenAffected || SomeFirstChildAffected || LineMoved ||
      IsContinuedComment || IsAffectedClosingBrace) {
    Line->Affected = true;
    SomeLineAffected = true;
  }
  return SomeLineAffected;
}

} // namespace format
} // namespace clang
