// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/ast/source-range-ast-visitor.h"

#include "src/ast/ast-source-ranges.h"

namespace v8 {
namespace internal {

SourceRangeAstVisitor::SourceRangeAstVisitor(uintptr_t stack_limit,
                                             Expression* root,
                                             SourceRangeMap* source_range_map)
    : AstTraversalVisitor(stack_limit, root),
      source_range_map_(source_range_map) {}

void SourceRangeAstVisitor::VisitBlock(Block* stmt) {
  AstTraversalVisitor::VisitBlock(stmt);
  ZonePtrList<Statement>* stmts = stmt->statements();
  AstNodeSourceRanges* enclosingSourceRanges = source_range_map_->Find(stmt);
  if (enclosingSourceRanges != nullptr) {
    CHECK(enclosingSourceRanges->HasRange(SourceRangeKind::kContinuation));
    MaybeRemoveLastContinuationRange(stmts);
  }
}

void SourceRangeAstVisitor::VisitSwitchStatement(SwitchStatement* stmt) {
  AstTraversalVisitor::VisitSwitchStatement(stmt);
  ZonePtrList<CaseClause>* clauses = stmt->cases();
  for (CaseClause* clause : *clauses) {
    MaybeRemoveLastContinuationRange(clause->statements());
  }
}

void SourceRangeAstVisitor::VisitFunctionLiteral(FunctionLiteral* expr) {
  AstTraversalVisitor::VisitFunctionLiteral(expr);
  ZonePtrList<Statement>* stmts = expr->body();
  MaybeRemoveLastContinuationRange(stmts);
}

void SourceRangeAstVisitor::VisitTryCatchStatement(TryCatchStatement* stmt) {
  AstTraversalVisitor::VisitTryCatchStatement(stmt);
  MaybeRemoveContinuationRange(stmt->try_block());
  MaybeRemoveContinuationRangeOfAsyncReturn(stmt);
}

void SourceRangeAstVisitor::VisitTryFinallyStatement(
    TryFinallyStatement* stmt) {
  AstTraversalVisitor::VisitTryFinallyStatement(stmt);
  MaybeRemoveContinuationRange(stmt->try_block());
}

bool SourceRangeAstVisitor::VisitNode(AstNode* node) {
  AstNodeSourceRanges* range = source_range_map_->Find(node);

  if (range == nullptr) return true;
  if (!range->HasRange(SourceRangeKind::kContinuation)) return true;

  // Called in pre-order. In case of conflicting continuation ranges, only the
  // outermost range may survive.

  SourceRange continuation = range->GetRange(SourceRangeKind::kContinuation);
  if (continuation_positions_.find(continuation.start) !=
      continuation_positions_.end()) {
    range->RemoveContinuationRange();
  } else {
    continuation_positions_.emplace(continuation.start);
  }

  return true;
}

void SourceRangeAstVisitor::MaybeRemoveContinuationRange(
    Statement* last_statement) {
  AstNodeSourceRanges* last_range = nullptr;

  if (last_statement->IsExpressionStatement() &&
      last_statement->AsExpressionStatement()->expression()->IsThrow()) {
    // For ThrowStatement, source range is tied to Throw expression not
    // ExpressionStatement.
    last_range = source_range_map_->Find(
        last_statement->AsExpressionStatement()->expression());
  } else {
    last_range = source_range_map_->Find(last_statement);
  }

  if (last_range == nullptr) return;

  if (last_range->HasRange(SourceRangeKind::kContinuation)) {
    last_range->RemoveContinuationRange();
  }
}

void SourceRangeAstVisitor::MaybeRemoveLastContinuationRange(
    ZonePtrList<Statement>* statements) {
  if (statements->is_empty()) return;
  MaybeRemoveContinuationRange(statements->last());
}

namespace {
Statement* FindLastNonSyntheticStatement(ZonePtrList<Statement>* statements) {
  for (int i = statements->length() - 1; i >= 0; --i) {
    Statement* stmt = statements->at(i);
    if (stmt->IsReturnStatement() &&
        stmt->AsReturnStatement()->is_synthetic_async_return()) {
      continue;
    }
    return stmt;
  }
  return nullptr;
}
}  // namespace

void SourceRangeAstVisitor::MaybeRemoveContinuationRangeOfAsyncReturn(
    TryCatchStatement* try_catch_stmt) {
  // Detect try-catch inserted by NewTryCatchStatementForAsyncAwait in the
  // parser (issued for async functions, including async generators), and
  // remove the continuation range of the last statement, such that the
  // range of the enclosing function body is used.
  if (try_catch_stmt->is_try_catch_for_async()) {
    Statement* last_non_synthetic =
      FindLastNonSyntheticStatement(try_catch_stmt->try_block()->statements());
    if (last_non_synthetic) {
      MaybeRemoveContinuationRange(last_non_synthetic);
    }
  }
}

}  // namespace internal
}  // namespace v8
