//===- unittest/Format/FormatTestBase.h - Formatting test base classs -----===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
//  This file defines the base class for format tests.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_UNITTESTS_FORMAT_FORMATTESTBASE_H
#define LLVM_CLANG_UNITTESTS_FORMAT_FORMATTESTBASE_H

#include "FormatTestUtils.h"

#include "clang/Format/Format.h"
#include "llvm/Support/Debug.h"
#include "gtest/gtest.h"

namespace clang {
namespace format {
namespace test {

#define DEBUG_TYPE "format-test-base"

class FormatTestBase : public testing::Test {
protected:
  enum StatusCheck { SC_ExpectComplete, SC_ExpectIncomplete, SC_DoNotCheck };

  virtual FormatStyle getDefaultStyle() const { return getLLVMStyle(); }

  virtual std::string messUp(StringRef Code) const {
    return test::messUp(Code);
  }

  std::string format(StringRef Code,
                     const std::optional<FormatStyle> &Style = {},
                     StatusCheck CheckComplete = SC_ExpectComplete,
                     const std::vector<tooling::Range> &Ranges = {}) {
    LLVM_DEBUG(llvm::errs() << "---\n");
    LLVM_DEBUG(llvm::errs() << Code << "\n\n");
    auto NonEmptyRanges =
        !Ranges.empty()
            ? Ranges
            : std::vector<tooling::Range>{1, tooling::Range(0, Code.size())};
    auto UsedStyle = Style ? Style.value() : getDefaultStyle();
    FormattingAttemptStatus Status;
    tooling::Replacements Replaces =
        reformat(UsedStyle, Code, NonEmptyRanges, "<stdin>", &Status);
    if (CheckComplete != SC_DoNotCheck) {
      bool ExpectedCompleteFormat = CheckComplete == SC_ExpectComplete;
      EXPECT_EQ(ExpectedCompleteFormat, Status.FormatComplete)
          << Code << "\n\n";
    }
    ReplacementCount = Replaces.size();
    auto Result = applyAllReplacements(Code, Replaces);
    EXPECT_TRUE(static_cast<bool>(Result));
    LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
    return *Result;
  }

  FormatStyle getStyleWithColumns(FormatStyle Style,
                                  unsigned ColumnLimit) const {
    Style.ColumnLimit = ColumnLimit;
    return Style;
  }

  FormatStyle getLLVMStyleWithColumns(unsigned ColumnLimit) const {
    return getStyleWithColumns(getLLVMStyle(), ColumnLimit);
  }

  FormatStyle getGoogleStyleWithColumns(unsigned ColumnLimit) const {
    return getStyleWithColumns(getGoogleStyle(), ColumnLimit);
  }

  FormatStyle getTextProtoStyleWithColumns(unsigned ColumnLimit) const {
    return getStyleWithColumns(getGoogleStyle(FormatStyle::LK_TextProto),
                               ColumnLimit);
  }

  bool _verifyFormat(const char *File, int Line, StringRef Expected,
                     StringRef Code,
                     const std::optional<FormatStyle> &Style = {},
                     const std::vector<tooling::Range> &Ranges = {}) {
    testing::ScopedTrace t(File, Line, testing::Message() << Code.str());
    const auto ExpectedCode{Expected.str()};
    auto FormattedCode{format(Code, Style, SC_ExpectComplete, Ranges)};
    EXPECT_EQ(ExpectedCode, FormattedCode);
    if (ExpectedCode != FormattedCode)
      return false;
    if (Expected != Code) {
      FormattedCode = format(Expected, Style, SC_ExpectComplete, Ranges);
      EXPECT_EQ(ExpectedCode, FormattedCode) << "Expected code is not stable";
      if (ExpectedCode != FormattedCode)
        return false;
    }
    auto UsedStyle = Style ? Style.value() : getDefaultStyle();
    if (UsedStyle.Language == FormatStyle::LK_Cpp) {
      // Objective-C++ is a superset of C++, so everything checked for C++
      // needs to be checked for Objective-C++ as well.
      FormatStyle ObjCStyle = UsedStyle;
      ObjCStyle.Language = FormatStyle::LK_ObjC;
      // FIXME: Additional messUp is superfluous.
      FormattedCode = format(Code, ObjCStyle, SC_ExpectComplete, Ranges);
      EXPECT_EQ(ExpectedCode, FormattedCode);
      if (ExpectedCode != FormattedCode)
        return false;
    }
    return true;
  }

  void _verifyFormat(const char *File, int Line, StringRef Code,
                     const std::optional<FormatStyle> &Style = {}) {
    if (!_verifyFormat(File, Line, Code, Code, Style))
      return;
    if (const auto MessedUpCode{messUp(Code)}; MessedUpCode != Code)
      _verifyFormat(File, Line, Code, MessedUpCode, Style);
  }

  void _verifyIncompleteFormat(const char *File, int Line, StringRef Code,
                               const std::optional<FormatStyle> &Style = {}) {
    testing::ScopedTrace t(File, Line, testing::Message() << Code.str());
    EXPECT_EQ(Code.str(), format(messUp(Code), Style, SC_ExpectIncomplete));
  }

  void
  _verifyIndependentOfContext(const char *File, int Line, StringRef Text,
                              const std::optional<FormatStyle> &Style = {}) {
    _verifyFormat(File, Line, Text, Style);
    _verifyFormat(File, Line, Twine("void f() { " + Text + " }").str(), Style);
  }

  void _verifyNoChange(const char *File, int Line, StringRef Code,
                       const std::optional<FormatStyle> &Style = {}) {
    _verifyFormat(File, Line, Code, Code, Style);
  }

  /// \brief Verify that clang-format does not crash on the given input.
  void verifyNoCrash(StringRef Code,
                     const std::optional<FormatStyle> &Style = {}) {
    format(Code, Style, SC_DoNotCheck);
  }

  int ReplacementCount;
};

#undef DEBUG_TYPE

#define verifyIndependentOfContext(...)                                        \
  _verifyIndependentOfContext(__FILE__, __LINE__, __VA_ARGS__)
#define verifyIncompleteFormat(...)                                            \
  _verifyIncompleteFormat(__FILE__, __LINE__, __VA_ARGS__)
#define verifyNoChange(...) _verifyNoChange(__FILE__, __LINE__, __VA_ARGS__)
#define verifyFormat(...) _verifyFormat(__FILE__, __LINE__, __VA_ARGS__)
#define verifyGoogleFormat(Code) verifyFormat(Code, getGoogleStyle())

} // namespace test
} // namespace format
} // namespace clang

#endif
