//===--- AffectedRangeManager.cpp - Format C++ code -----------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief This file implements AffectRangeManager class.
///
//===----------------------------------------------------------------------===//

#include "AffectedRangeManager.h"

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

namespace clang {
namespace format {

bool AffectedRangeManager::computeAffectedLines(
    SmallVectorImpl<AnnotatedLine *>::iterator I,
    SmallVectorImpl<AnnotatedLine *>::iterator E) {
  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))
      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) {
  bool SomeLineAffected = false;
  Line->ChildrenAffected =
      computeAffectedLines(Line->Children.begin(), Line->Children.end());
  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);

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

} // namespace format
} // namespace clang
