//===------ IndexActionTests.cpp  -------------------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "Headers.h"
#include "TestFS.h"
#include "URI.h"
#include "index/IndexAction.h"
#include "index/Serialization.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Tooling/Tooling.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <string>

namespace clang {
namespace clangd {
namespace {

using ::testing::AllOf;
using ::testing::ElementsAre;
using ::testing::EndsWith;
using ::testing::Not;
using ::testing::Pair;
using ::testing::UnorderedElementsAre;
using ::testing::UnorderedPointwise;

std::string toUri(llvm::StringRef Path) { return URI::create(Path).toString(); }

MATCHER(isTU, "") { return arg.Flags & IncludeGraphNode::SourceFlag::IsTU; }

MATCHER_P(hasDigest, Digest, "") { return arg.Digest == Digest; }

MATCHER_P(hasName, Name, "") { return arg.Name == Name; }

MATCHER(hasSameURI, "") {
  llvm::StringRef URI = ::testing::get<0>(arg);
  const std::string &Path = ::testing::get<1>(arg);
  return toUri(Path) == URI;
}

MATCHER_P(includeHeader, P, "") {
  return (arg.IncludeHeaders.size() == 1) &&
         (arg.IncludeHeaders.begin()->IncludeHeader == P);
}

::testing::Matcher<const IncludeGraphNode &>
includesAre(const std::vector<std::string> &Includes) {
  return ::testing::Field(&IncludeGraphNode::DirectIncludes,
                          UnorderedPointwise(hasSameURI(), Includes));
}

void checkNodesAreInitialized(const IndexFileIn &IndexFile,
                              const std::vector<std::string> &Paths) {
  ASSERT_TRUE(IndexFile.Sources);
  EXPECT_THAT(Paths.size(), IndexFile.Sources->size());
  for (llvm::StringRef Path : Paths) {
    auto URI = toUri(Path);
    const auto &Node = IndexFile.Sources->lookup(URI);
    // Uninitialized nodes will have an empty URI.
    EXPECT_EQ(Node.URI.data(), IndexFile.Sources->find(URI)->getKeyData());
  }
}

std::map<std::string, const IncludeGraphNode &> toMap(const IncludeGraph &IG) {
  std::map<std::string, const IncludeGraphNode &> Nodes;
  for (auto &I : IG)
    Nodes.emplace(std::string(I.getKey()), I.getValue());
  return Nodes;
}

class IndexActionTest : public ::testing::Test {
public:
  IndexActionTest() : InMemoryFileSystem(new llvm::vfs::InMemoryFileSystem) {}

  IndexFileIn
  runIndexingAction(llvm::StringRef MainFilePath,
                    const std::vector<std::string> &ExtraArgs = {}) {
    IndexFileIn IndexFile;
    llvm::IntrusiveRefCntPtr<FileManager> Files(
        new FileManager(FileSystemOptions(), InMemoryFileSystem));

    auto Action = createStaticIndexingAction(
        Opts, [&](SymbolSlab S) { IndexFile.Symbols = std::move(S); },
        [&](RefSlab R) { IndexFile.Refs = std::move(R); },
        [&](RelationSlab R) { IndexFile.Relations = std::move(R); },
        [&](IncludeGraph IG) { IndexFile.Sources = std::move(IG); });

    std::vector<std::string> Args = {"index_action", "-fsyntax-only",
                                     "-xc++",        "-std=c++11",
                                     "-iquote",      testRoot()};
    Args.insert(Args.end(), ExtraArgs.begin(), ExtraArgs.end());
    Args.push_back(std::string(MainFilePath));

    tooling::ToolInvocation Invocation(
        Args, std::move(Action), Files.get(),
        std::make_shared<PCHContainerOperations>());

    Invocation.run();

    checkNodesAreInitialized(IndexFile, FilePaths);
    return IndexFile;
  }

  void addFile(llvm::StringRef Path, llvm::StringRef Content) {
    InMemoryFileSystem->addFile(Path, 0,
                                llvm::MemoryBuffer::getMemBufferCopy(Content));
    FilePaths.push_back(std::string(Path));
  }

protected:
  SymbolCollector::Options Opts;
  std::vector<std::string> FilePaths;
  llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem;
};

TEST_F(IndexActionTest, CollectIncludeGraph) {
  std::string MainFilePath = testPath("main.cpp");
  std::string MainCode = "#include \"level1.h\"";
  std::string Level1HeaderPath = testPath("level1.h");
  std::string Level1HeaderCode = "#include \"level2.h\"";
  std::string Level2HeaderPath = testPath("level2.h");
  std::string Level2HeaderCode = "";

  addFile(MainFilePath, MainCode);
  addFile(Level1HeaderPath, Level1HeaderCode);
  addFile(Level2HeaderPath, Level2HeaderCode);

  IndexFileIn IndexFile = runIndexingAction(MainFilePath);
  auto Nodes = toMap(*IndexFile.Sources);

  EXPECT_THAT(Nodes,
              UnorderedElementsAre(
                  Pair(toUri(MainFilePath),
                       AllOf(isTU(), includesAre({Level1HeaderPath}),
                             hasDigest(digest(MainCode)))),
                  Pair(toUri(Level1HeaderPath),
                       AllOf(Not(isTU()), includesAre({Level2HeaderPath}),
                             hasDigest(digest(Level1HeaderCode)))),
                  Pair(toUri(Level2HeaderPath),
                       AllOf(Not(isTU()), includesAre({}),
                             hasDigest(digest(Level2HeaderCode))))));
}

TEST_F(IndexActionTest, IncludeGraphSelfInclude) {
  std::string MainFilePath = testPath("main.cpp");
  std::string MainCode = "#include \"header.h\"";
  std::string HeaderPath = testPath("header.h");
  std::string HeaderCode = R"cpp(
      #ifndef _GUARD_
      #define _GUARD_
      #include "header.h"
      #endif)cpp";

  addFile(MainFilePath, MainCode);
  addFile(HeaderPath, HeaderCode);

  IndexFileIn IndexFile = runIndexingAction(MainFilePath);
  auto Nodes = toMap(*IndexFile.Sources);

  EXPECT_THAT(
      Nodes,
      UnorderedElementsAre(
          Pair(toUri(MainFilePath), AllOf(isTU(), includesAre({HeaderPath}),
                                          hasDigest(digest(MainCode)))),
          Pair(toUri(HeaderPath), AllOf(Not(isTU()), includesAre({HeaderPath}),
                                        hasDigest(digest(HeaderCode))))));
}

TEST_F(IndexActionTest, IncludeGraphSkippedFile) {
  std::string MainFilePath = testPath("main.cpp");
  std::string MainCode = R"cpp(
      #include "common.h"
      #include "header.h"
      )cpp";

  std::string CommonHeaderPath = testPath("common.h");
  std::string CommonHeaderCode = R"cpp(
      #ifndef _GUARD_
      #define _GUARD_
      void f();
      #endif)cpp";

  std::string HeaderPath = testPath("header.h");
  std::string HeaderCode = R"cpp(
      #include "common.h"
      void g();)cpp";

  addFile(MainFilePath, MainCode);
  addFile(HeaderPath, HeaderCode);
  addFile(CommonHeaderPath, CommonHeaderCode);

  IndexFileIn IndexFile = runIndexingAction(MainFilePath);
  auto Nodes = toMap(*IndexFile.Sources);

  EXPECT_THAT(
      Nodes, UnorderedElementsAre(
                 Pair(toUri(MainFilePath),
                      AllOf(isTU(), includesAre({HeaderPath, CommonHeaderPath}),
                            hasDigest(digest(MainCode)))),
                 Pair(toUri(HeaderPath),
                      AllOf(Not(isTU()), includesAre({CommonHeaderPath}),
                            hasDigest(digest(HeaderCode)))),
                 Pair(toUri(CommonHeaderPath),
                      AllOf(Not(isTU()), includesAre({}),
                            hasDigest(digest(CommonHeaderCode))))));
}

TEST_F(IndexActionTest, IncludeGraphDynamicInclude) {
  std::string MainFilePath = testPath("main.cpp");
  std::string MainCode = R"cpp(
      #ifndef FOO
      #define FOO "main.cpp"
      #else
      #define FOO "header.h"
      #endif

      #include FOO)cpp";
  std::string HeaderPath = testPath("header.h");
  std::string HeaderCode = "";

  addFile(MainFilePath, MainCode);
  addFile(HeaderPath, HeaderCode);

  IndexFileIn IndexFile = runIndexingAction(MainFilePath);
  auto Nodes = toMap(*IndexFile.Sources);

  EXPECT_THAT(
      Nodes,
      UnorderedElementsAre(
          Pair(toUri(MainFilePath),
               AllOf(isTU(), includesAre({MainFilePath, HeaderPath}),
                     hasDigest(digest(MainCode)))),
          Pair(toUri(HeaderPath), AllOf(Not(isTU()), includesAre({}),
                                        hasDigest(digest(HeaderCode))))));
}

TEST_F(IndexActionTest, NoWarnings) {
  std::string MainFilePath = testPath("main.cpp");
  std::string MainCode = R"cpp(
      void foo(int x) {
        if (x = 1) // -Wparentheses
          return;
        if (x = 1) // -Wparentheses
          return;
      }
      void bar() {}
  )cpp";
  addFile(MainFilePath, MainCode);
  // We set -ferror-limit so the warning-promoted-to-error would be fatal.
  // This would cause indexing to stop (if warnings weren't disabled).
  IndexFileIn IndexFile = runIndexingAction(
      MainFilePath, {"-ferror-limit=1", "-Wparentheses", "-Werror"});
  ASSERT_TRUE(IndexFile.Sources);
  ASSERT_NE(0u, IndexFile.Sources->size());
  EXPECT_THAT(*IndexFile.Symbols, ElementsAre(hasName("foo"), hasName("bar")));
}

TEST_F(IndexActionTest, SkipFiles) {
  std::string MainFilePath = testPath("main.cpp");
  addFile(MainFilePath, R"cpp(
    // clang-format off
    #include "good.h"
    #include "bad.h"
    // clang-format on
  )cpp");
  addFile(testPath("good.h"), R"cpp(
    struct S { int s; };
    void f1() { S f; }
    auto unskippable1() { return S(); }
  )cpp");
  addFile(testPath("bad.h"), R"cpp(
    struct T { S t; };
    void f2() { S f; }
    auto unskippable2() { return S(); }
  )cpp");
  Opts.FileFilter = [](const SourceManager &SM, FileID F) {
    return !SM.getFileEntryRefForID(F)->getName().ends_with("bad.h");
  };
  IndexFileIn IndexFile = runIndexingAction(MainFilePath, {"-std=c++14"});
  EXPECT_THAT(*IndexFile.Symbols,
              UnorderedElementsAre(hasName("S"), hasName("s"), hasName("f1"),
                                   hasName("unskippable1")));
  for (const auto &Pair : *IndexFile.Refs)
    for (const auto &Ref : Pair.second)
      EXPECT_THAT(Ref.Location.FileURI, EndsWith("good.h"));
}

TEST_F(IndexActionTest, SkipNestedSymbols) {
  std::string MainFilePath = testPath("main.cpp");
  addFile(MainFilePath, R"cpp(
  namespace ns1 {
  namespace ns2 {
  namespace ns3 {
  namespace ns4 {
  namespace ns5 {
  namespace ns6 {
  namespace ns7 {
  namespace ns8 {
  namespace ns9 {
  class Bar {};
  void foo() {
    class Baz {};
  }
  }
  }
  }
  }
  }
  }
  }
  }
  })cpp");
  IndexFileIn IndexFile = runIndexingAction(MainFilePath, {"-std=c++14"});
  EXPECT_THAT(*IndexFile.Symbols, testing::Contains(hasName("foo")));
  EXPECT_THAT(*IndexFile.Symbols, testing::Contains(hasName("Bar")));
  EXPECT_THAT(*IndexFile.Symbols, Not(testing::Contains(hasName("Baz"))));
}

TEST_F(IndexActionTest, SymbolFromCC) {
  std::string MainFilePath = testPath("main.cpp");
  addFile(MainFilePath, R"cpp(
 #include "main.h"
 void foo() {}
 )cpp");
  addFile(testPath("main.h"), R"cpp(
 #pragma once
 void foo();
 )cpp");
  Opts.FileFilter = [](const SourceManager &SM, FileID F) {
    return !SM.getFileEntryRefForID(F)->getName().ends_with("main.h");
  };
  IndexFileIn IndexFile = runIndexingAction(MainFilePath, {"-std=c++14"});
  EXPECT_THAT(*IndexFile.Symbols,
              UnorderedElementsAre(AllOf(
                  hasName("foo"),
                  includeHeader(URI::create(testPath("main.h")).toString()))));
}

TEST_F(IndexActionTest, IncludeHeaderForwardDecls) {
  std::string MainFilePath = testPath("main.cpp");
  addFile(MainFilePath, R"cpp(
#include "fwd.h"
#include "full.h"
 )cpp");
  addFile(testPath("fwd.h"), R"cpp(
#ifndef _FWD_H_
#define _FWD_H_
struct Foo;
#endif
 )cpp");
  addFile(testPath("full.h"), R"cpp(
#ifndef _FULL_H_
#define _FULL_H_
struct Foo {};

// This decl is important, as otherwise we detect control macro for the file,
// before handling definition of Foo.
void other();
#endif
 )cpp");
  IndexFileIn IndexFile = runIndexingAction(MainFilePath);
  EXPECT_THAT(*IndexFile.Symbols,
              testing::Contains(AllOf(
                  hasName("Foo"),
                  includeHeader(URI::create(testPath("full.h")).toString()))))
      << *IndexFile.Symbols->begin();
}
} // namespace
} // namespace clangd
} // namespace clang
