//===- 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(llvm::StringRef Code) const {
    return test::messUp(Code);
  }

  std::string format(llvm::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) {
    Style.ColumnLimit = ColumnLimit;
    return Style;
  }

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

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

  FormatStyle getTextProtoStyleWithColumns(unsigned ColumnLimit) {
    FormatStyle Style = getGoogleStyle(FormatStyle::FormatStyle::LK_TextProto);
    Style.ColumnLimit = ColumnLimit;
    return Style;
  }

  bool _verifyFormat(const char *File, int Line, llvm::StringRef Expected,
                     llvm::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, llvm::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, llvm::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, llvm::StringRef Text,
                              const std::optional<FormatStyle> &Style = {}) {
    _verifyFormat(File, Line, Text, Style);
    _verifyFormat(File, Line, llvm::Twine("void f() { " + Text + " }").str(),
                  Style);
  }

  void _verifyNoChange(const char *File, int Line, llvm::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(llvm::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
