//===--- Check.cpp - clangd self-diagnostics ------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Many basic problems can occur processing a file in clangd, e.g.:
//  - system includes are not found
//  - crash when indexing its AST
// clangd --check provides a simplified, isolated way to reproduce these,
// with no editor, LSP, threads, background indexing etc to contend with.
//
// One important use case is gathering information for bug reports.
// Another is reproducing crashes, and checking which setting prevent them.
//
// It simulates opening a file (determining compile command, parsing, indexing)
// and then running features at many locations.
//
// Currently it adds some basic logging of progress and results.
// We should consider extending it to also recognize common symptoms and
// recommend solutions (e.g. standard library installation issues).
//
//===----------------------------------------------------------------------===//

#include "ClangdLSPServer.h"
#include "CodeComplete.h"
#include "Config.h"
#include "GlobalCompilationDatabase.h"
#include "Hover.h"
#include "ParsedAST.h"
#include "Preamble.h"
#include "SourceCode.h"
#include "XRefs.h"
#include "index/CanonicalIncludes.h"
#include "index/FileIndex.h"
#include "refactor/Tweak.h"
#include "support/ThreadsafeFS.h"
#include "support/Trace.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Format/Format.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Path.h"

namespace clang {
namespace clangd {
namespace {

// Print (and count) the error-level diagnostics (warnings are ignored).
unsigned showErrors(llvm::ArrayRef<Diag> Diags) {
  unsigned ErrCount = 0;
  for (const auto &D : Diags) {
    if (D.Severity >= DiagnosticsEngine::Error) {
      elog("[{0}] Line {1}: {2}", D.Name, D.Range.start.line + 1, D.Message);
      ++ErrCount;
    }
  }
  return ErrCount;
}

// This class is just a linear pipeline whose functions get called in sequence.
// Each exercises part of clangd's logic on our test file and logs results.
// Later steps depend on state built in earlier ones (such as the AST).
// Many steps can fatally fail (return false), then subsequent ones cannot run.
// Nonfatal failures are logged and tracked in ErrCount.
class Checker {
  // from constructor
  std::string File;
  ClangdLSPServer::Options Opts;
  // from buildCommand
  tooling::CompileCommand Cmd;
  // from buildInvocation
  ParseInputs Inputs;
  std::unique_ptr<CompilerInvocation> Invocation;
  format::FormatStyle Style;
  // from buildAST
  std::shared_ptr<const PreambleData> Preamble;
  llvm::Optional<ParsedAST> AST;
  FileIndex Index;

public:
  // Number of non-fatal errors seen.
  unsigned ErrCount = 0;

  Checker(llvm::StringRef File, const ClangdLSPServer::Options &Opts)
      : File(File), Opts(Opts) {}

  // Read compilation database and choose a compile command for the file.
  bool buildCommand(const ThreadsafeFS &TFS) {
    log("Loading compilation database...");
    DirectoryBasedGlobalCompilationDatabase::Options CDBOpts(TFS);
    CDBOpts.CompileCommandsDir =
        Config::current().CompileFlags.CDBSearch.FixedCDBPath;
    std::unique_ptr<GlobalCompilationDatabase> BaseCDB =
        std::make_unique<DirectoryBasedGlobalCompilationDatabase>(CDBOpts);
    BaseCDB = getQueryDriverDatabase(llvm::makeArrayRef(Opts.QueryDriverGlobs),
                                     std::move(BaseCDB));
    auto Mangler = CommandMangler::detect();
    if (Opts.ResourceDir)
      Mangler.ResourceDir = *Opts.ResourceDir;
    auto CDB = std::make_unique<OverlayCDB>(
        BaseCDB.get(), std::vector<std::string>{},
        tooling::ArgumentsAdjuster(std::move(Mangler)));

    if (auto TrueCmd = CDB->getCompileCommand(File)) {
      Cmd = std::move(*TrueCmd);
      log("Compile command from CDB is: {0}", printArgv(Cmd.CommandLine));
    } else {
      Cmd = CDB->getFallbackCommand(File);
      log("Generic fallback command is: {0}", printArgv(Cmd.CommandLine));
    }

    return true;
  }

  // Prepare inputs and build CompilerInvocation (parsed compile command).
  bool buildInvocation(const ThreadsafeFS &TFS,
                       llvm::Optional<std::string> Contents) {
    StoreDiags CaptureInvocationDiags;
    std::vector<std::string> CC1Args;
    Inputs.CompileCommand = Cmd;
    Inputs.TFS = &TFS;
    Inputs.ClangTidyProvider = Opts.ClangTidyProvider;
    if (Contents.hasValue()) {
      Inputs.Contents = *Contents;
      log("Imaginary source file contents:\n{0}", Inputs.Contents);
    } else {
      if (auto Contents = TFS.view(llvm::None)->getBufferForFile(File)) {
        Inputs.Contents = Contents->get()->getBuffer().str();
      } else {
        elog("Couldn't read {0}: {1}", File, Contents.getError().message());
        return false;
      }
    }
    log("Parsing command...");
    Invocation =
        buildCompilerInvocation(Inputs, CaptureInvocationDiags, &CC1Args);
    auto InvocationDiags = CaptureInvocationDiags.take();
    ErrCount += showErrors(InvocationDiags);
    log("internal (cc1) args are: {0}", printArgv(CC1Args));
    if (!Invocation) {
      elog("Failed to parse command line");
      return false;
    }

    // FIXME: Check that resource-dir/built-in-headers exist?

    Style = getFormatStyleForFile(File, Inputs.Contents, TFS);

    return true;
  }

  // Build preamble and AST, and index them.
  bool buildAST() {
    log("Building preamble...");
    Preamble =
        buildPreamble(File, *Invocation, Inputs, /*StoreInMemory=*/true,
                      [&](ASTContext &Ctx, std::shared_ptr<Preprocessor> PP,
                          const CanonicalIncludes &Includes) {
                        if (!Opts.BuildDynamicSymbolIndex)
                          return;
                        log("Indexing headers...");
                        Index.updatePreamble(File, /*Version=*/"null", Ctx,
                                             std::move(PP), Includes);
                      });
    if (!Preamble) {
      elog("Failed to build preamble");
      return false;
    }
    ErrCount += showErrors(Preamble->Diags);

    log("Building AST...");
    AST = ParsedAST::build(File, Inputs, std::move(Invocation),
                           /*InvocationDiags=*/std::vector<Diag>{}, Preamble);
    if (!AST) {
      elog("Failed to build AST");
      return false;
    }
    ErrCount += showErrors(llvm::makeArrayRef(*AST->getDiagnostics())
                               .drop_front(Preamble->Diags.size()));

    if (Opts.BuildDynamicSymbolIndex) {
      log("Indexing AST...");
      Index.updateMain(File, *AST);
    }
    return true;
  }

  // Run AST-based features at each token in the file.
  void testLocationFeatures(
      llvm::function_ref<bool(const Position &)> ShouldCheckLine,
      const bool EnableCodeCompletion) {
    trace::Span Trace("testLocationFeatures");
    log("Testing features at each token (may be slow in large files)");
    auto &SM = AST->getSourceManager();
    auto SpelledTokens = AST->getTokens().spelledTokens(SM.getMainFileID());

    CodeCompleteOptions CCOpts = Opts.CodeComplete;
    CCOpts.Index = &Index;

    for (const auto &Tok : SpelledTokens) {
      unsigned Start = AST->getSourceManager().getFileOffset(Tok.location());
      unsigned End = Start + Tok.length();
      Position Pos = offsetToPosition(Inputs.Contents, Start);

      if (!ShouldCheckLine(Pos))
        continue;

      trace::Span Trace("Token");
      SPAN_ATTACH(Trace, "pos", Pos);
      SPAN_ATTACH(Trace, "text", Tok.text(AST->getSourceManager()));

      // FIXME: dumping the tokens may leak sensitive code into bug reports.
      // Add an option to turn this off, once we decide how options work.
      vlog("  {0} {1}", Pos, Tok.text(AST->getSourceManager()));
      auto Tree = SelectionTree::createRight(AST->getASTContext(),
                                             AST->getTokens(), Start, End);
      Tweak::Selection Selection(&Index, *AST, Start, End, std::move(Tree),
                                 nullptr);
      // FS is only populated when applying a tweak, not during prepare as
      // prepare should not do any I/O to be fast.
      auto Tweaks =
          prepareTweaks(Selection, Opts.TweakFilter, Opts.FeatureModules);
      Selection.FS =
          &AST->getSourceManager().getFileManager().getVirtualFileSystem();
      for (const auto &T : Tweaks) {
        auto Result = T->apply(Selection);
        if (!Result) {
          elog("    tweak: {0} ==> FAIL: {1}", T->id(), Result.takeError());
          ++ErrCount;
        } else {
          vlog("    tweak: {0}", T->id());
        }
      }
      unsigned Definitions = locateSymbolAt(*AST, Pos, &Index).size();
      vlog("    definition: {0}", Definitions);

      auto Hover = getHover(*AST, Pos, Style, &Index);
      vlog("    hover: {0}", Hover.hasValue());

      if (EnableCodeCompletion) {
        Position EndPos = offsetToPosition(Inputs.Contents, End);
        auto CC = codeComplete(File, EndPos, Preamble.get(), Inputs, CCOpts);
        vlog("    code completion: {0}",
             CC.Completions.empty() ? "<empty>" : CC.Completions[0].Name);
      }
    }
  }
};

} // namespace

bool check(llvm::StringRef File,
           llvm::function_ref<bool(const Position &)> ShouldCheckLine,
           const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts,
           bool EnableCodeCompletion) {
  llvm::SmallString<0> FakeFile;
  llvm::Optional<std::string> Contents;
  if (File.empty()) {
    llvm::sys::path::system_temp_directory(false, FakeFile);
    llvm::sys::path::append(FakeFile, "test.cc");
    File = FakeFile;
    Contents = R"cpp(
      #include <stddef.h>
      #include <string>

      size_t N = 50;
      auto xxx = std::string(N, 'x');
    )cpp";
  }
  log("Testing on source file {0}", File);

  auto ContextProvider = ClangdServer::createConfiguredContextProvider(
      Opts.ConfigProvider, nullptr);
  WithContext Ctx(ContextProvider(
      FakeFile.empty()
          ? File
          : /*Don't turn on local configs for an arbitrary temp path.*/ ""));
  Checker C(File, Opts);
  if (!C.buildCommand(TFS) || !C.buildInvocation(TFS, Contents) ||
      !C.buildAST())
    return false;
  C.testLocationFeatures(ShouldCheckLine, EnableCodeCompletion);

  log("All checks completed, {0} errors", C.ErrCount);
  return C.ErrCount == 0;
}

} // namespace clangd
} // namespace clang
