//===-- IncludeFixer.cpp - Include inserter based on sema callbacks -------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "IncludeFixer.h"
#include "clang/Format/Format.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/ParseAST.h"
#include "clang/Sema/Sema.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"

#define DEBUG_TYPE "include-fixer"

using namespace clang;

namespace clang {
namespace include_fixer {
namespace {
/// Manages the parse, gathers include suggestions.
class Action : public clang::ASTFrontendAction {
public:
  explicit Action(SymbolIndexManager &SymbolIndexMgr, bool MinimizeIncludePaths)
      : SemaSource(SymbolIndexMgr, MinimizeIncludePaths,
                   /*GenerateDiagnostics=*/false) {}

  std::unique_ptr<clang::ASTConsumer>
  CreateASTConsumer(clang::CompilerInstance &Compiler,
                    StringRef InFile) override {
    SemaSource.setFilePath(InFile);
    return llvm::make_unique<clang::ASTConsumer>();
  }

  void ExecuteAction() override {
    clang::CompilerInstance *Compiler = &getCompilerInstance();
    assert(!Compiler->hasSema() && "CI already has Sema");

    // Set up our hooks into sema and parse the AST.
    if (hasCodeCompletionSupport() &&
        !Compiler->getFrontendOpts().CodeCompletionAt.FileName.empty())
      Compiler->createCodeCompletionConsumer();

    clang::CodeCompleteConsumer *CompletionConsumer = nullptr;
    if (Compiler->hasCodeCompletionConsumer())
      CompletionConsumer = &Compiler->getCodeCompletionConsumer();

    Compiler->createSema(getTranslationUnitKind(), CompletionConsumer);
    SemaSource.setCompilerInstance(Compiler);
    Compiler->getSema().addExternalSource(&SemaSource);

    clang::ParseAST(Compiler->getSema(), Compiler->getFrontendOpts().ShowStats,
                    Compiler->getFrontendOpts().SkipFunctionBodies);
  }

  IncludeFixerContext
  getIncludeFixerContext(const clang::SourceManager &SourceManager,
                         clang::HeaderSearch &HeaderSearch) const {
    return SemaSource.getIncludeFixerContext(SourceManager, HeaderSearch,
                                             SemaSource.getMatchedSymbols());
  }

private:
  IncludeFixerSemaSource SemaSource;
};

} // namespace

IncludeFixerActionFactory::IncludeFixerActionFactory(
    SymbolIndexManager &SymbolIndexMgr,
    std::vector<IncludeFixerContext> &Contexts, StringRef StyleName,
    bool MinimizeIncludePaths)
    : SymbolIndexMgr(SymbolIndexMgr), Contexts(Contexts),
      MinimizeIncludePaths(MinimizeIncludePaths) {}

IncludeFixerActionFactory::~IncludeFixerActionFactory() = default;

bool IncludeFixerActionFactory::runInvocation(
    std::shared_ptr<clang::CompilerInvocation> Invocation,
    clang::FileManager *Files,
    std::shared_ptr<clang::PCHContainerOperations> PCHContainerOps,
    clang::DiagnosticConsumer *Diagnostics) {
  assert(Invocation->getFrontendOpts().Inputs.size() == 1);

  // Set up Clang.
  clang::CompilerInstance Compiler(PCHContainerOps);
  Compiler.setInvocation(std::move(Invocation));
  Compiler.setFileManager(Files);

  // Create the compiler's actual diagnostics engine. We want to drop all
  // diagnostics here.
  Compiler.createDiagnostics(new clang::IgnoringDiagConsumer,
                             /*ShouldOwnClient=*/true);
  Compiler.createSourceManager(*Files);

  // We abort on fatal errors so don't let a large number of errors become
  // fatal. A missing #include can cause thousands of errors.
  Compiler.getDiagnostics().setErrorLimit(0);

  // Run the parser, gather missing includes.
  auto ScopedToolAction =
      llvm::make_unique<Action>(SymbolIndexMgr, MinimizeIncludePaths);
  Compiler.ExecuteAction(*ScopedToolAction);

  Contexts.push_back(ScopedToolAction->getIncludeFixerContext(
      Compiler.getSourceManager(),
      Compiler.getPreprocessor().getHeaderSearchInfo()));

  // Technically this should only return true if we're sure that we have a
  // parseable file. We don't know that though. Only inform users of fatal
  // errors.
  return !Compiler.getDiagnostics().hasFatalErrorOccurred();
}

static bool addDiagnosticsForContext(TypoCorrection &Correction,
                                     const IncludeFixerContext &Context,
                                     StringRef Code, SourceLocation StartOfFile,
                                     ASTContext &Ctx) {
  auto Reps = createIncludeFixerReplacements(
      Code, Context, format::getLLVMStyle(), /*AddQualifiers=*/false);
  if (!Reps || Reps->size() != 1)
    return false;

  unsigned DiagID = Ctx.getDiagnostics().getCustomDiagID(
      DiagnosticsEngine::Note, "Add '#include %0' to provide the missing "
                               "declaration [clang-include-fixer]");

  // FIXME: Currently we only generate a diagnostic for the first header. Give
  // the user choices.
  const tooling::Replacement &Placed = *Reps->begin();

  auto Begin = StartOfFile.getLocWithOffset(Placed.getOffset());
  auto End = Begin.getLocWithOffset(std::max(0, (int)Placed.getLength() - 1));
  PartialDiagnostic PD(DiagID, Ctx.getDiagAllocator());
  PD << Context.getHeaderInfos().front().Header
     << FixItHint::CreateReplacement(CharSourceRange::getCharRange(Begin, End),
                                     Placed.getReplacementText());
  Correction.addExtraDiagnostic(std::move(PD));
  return true;
}

/// Callback for incomplete types. If we encounter a forward declaration we
/// have the fully qualified name ready. Just query that.
bool IncludeFixerSemaSource::MaybeDiagnoseMissingCompleteType(
    clang::SourceLocation Loc, clang::QualType T) {
  // Ignore spurious callbacks from SFINAE contexts.
  if (CI->getSema().isSFINAEContext())
    return false;

  clang::ASTContext &context = CI->getASTContext();
  std::string QueryString = QualType(T->getUnqualifiedDesugaredType(), 0)
                                .getAsString(context.getPrintingPolicy());
  LLVM_DEBUG(llvm::dbgs() << "Query missing complete type '" << QueryString
                          << "'");
  // Pass an empty range here since we don't add qualifier in this case.
  std::vector<find_all_symbols::SymbolInfo> MatchedSymbols =
      query(QueryString, "", tooling::Range());

  if (!MatchedSymbols.empty() && GenerateDiagnostics) {
    TypoCorrection Correction;
    FileID FID = CI->getSourceManager().getFileID(Loc);
    StringRef Code = CI->getSourceManager().getBufferData(FID);
    SourceLocation StartOfFile =
        CI->getSourceManager().getLocForStartOfFile(FID);
    addDiagnosticsForContext(
        Correction,
        getIncludeFixerContext(CI->getSourceManager(),
                               CI->getPreprocessor().getHeaderSearchInfo(),
                               MatchedSymbols),
        Code, StartOfFile, CI->getASTContext());
    for (const PartialDiagnostic &PD : Correction.getExtraDiagnostics())
      CI->getSema().Diag(Loc, PD);
  }
  return true;
}

/// Callback for unknown identifiers. Try to piece together as much
/// qualification as we can get and do a query.
clang::TypoCorrection IncludeFixerSemaSource::CorrectTypo(
    const DeclarationNameInfo &Typo, int LookupKind, Scope *S, CXXScopeSpec *SS,
    CorrectionCandidateCallback &CCC, DeclContext *MemberContext,
    bool EnteringContext, const ObjCObjectPointerType *OPT) {
  // Ignore spurious callbacks from SFINAE contexts.
  if (CI->getSema().isSFINAEContext())
    return clang::TypoCorrection();

  // We currently ignore the unidentified symbol which is not from the
  // main file.
  //
  // However, this is not always true due to templates in a non-self contained
  // header, consider the case:
  //
  //   // header.h
  //   template <typename T>
  //   class Foo {
  //     T t;
  //   };
  //
  //   // test.cc
  //   // We need to add <bar.h> in test.cc instead of header.h.
  //   class Bar;
  //   Foo<Bar> foo;
  //
  // FIXME: Add the missing header to the header file where the symbol comes
  // from.
  if (!CI->getSourceManager().isWrittenInMainFile(Typo.getLoc()))
    return clang::TypoCorrection();

  std::string TypoScopeString;
  if (S) {
    // FIXME: Currently we only use namespace contexts. Use other context
    // types for query.
    for (const auto *Context = S->getEntity(); Context;
         Context = Context->getParent()) {
      if (const auto *ND = dyn_cast<NamespaceDecl>(Context)) {
        if (!ND->getName().empty())
          TypoScopeString = ND->getNameAsString() + "::" + TypoScopeString;
      }
    }
  }

  auto ExtendNestedNameSpecifier = [this](CharSourceRange Range) {
    StringRef Source =
        Lexer::getSourceText(Range, CI->getSourceManager(), CI->getLangOpts());

    // Skip forward until we find a character that's neither identifier nor
    // colon. This is a bit of a hack around the fact that we will only get a
    // single callback for a long nested name if a part of the beginning is
    // unknown. For example:
    //
    // llvm::sys::path::parent_path(...)
    // ^~~~  ^~~
    //    known
    //            ^~~~
    //      unknown, last callback
    //                  ^~~~~~~~~~~
    //                  no callback
    //
    // With the extension we get the full nested name specifier including
    // parent_path.
    // FIXME: Don't rely on source text.
    const char *End = Source.end();
    while (isIdentifierBody(*End) || *End == ':')
      ++End;

    return std::string(Source.begin(), End);
  };

  /// If we have a scope specification, use that to get more precise results.
  std::string QueryString;
  tooling::Range SymbolRange;
  const auto &SM = CI->getSourceManager();
  auto CreateToolingRange = [&QueryString, &SM](SourceLocation BeginLoc) {
    return tooling::Range(SM.getDecomposedLoc(BeginLoc).second,
                          QueryString.size());
  };
  if (SS && SS->getRange().isValid()) {
    auto Range = CharSourceRange::getTokenRange(SS->getRange().getBegin(),
                                                Typo.getLoc());

    QueryString = ExtendNestedNameSpecifier(Range);
    SymbolRange = CreateToolingRange(Range.getBegin());
  } else if (Typo.getName().isIdentifier() && !Typo.getLoc().isMacroID()) {
    auto Range =
        CharSourceRange::getTokenRange(Typo.getBeginLoc(), Typo.getEndLoc());

    QueryString = ExtendNestedNameSpecifier(Range);
    SymbolRange = CreateToolingRange(Range.getBegin());
  } else {
    QueryString = Typo.getAsString();
    SymbolRange = CreateToolingRange(Typo.getLoc());
  }

  LLVM_DEBUG(llvm::dbgs() << "TypoScopeQualifiers: " << TypoScopeString
                          << "\n");
  std::vector<find_all_symbols::SymbolInfo> MatchedSymbols =
      query(QueryString, TypoScopeString, SymbolRange);

  if (!MatchedSymbols.empty() && GenerateDiagnostics) {
    TypoCorrection Correction(Typo.getName());
    Correction.setCorrectionRange(SS, Typo);
    FileID FID = SM.getFileID(Typo.getLoc());
    StringRef Code = SM.getBufferData(FID);
    SourceLocation StartOfFile = SM.getLocForStartOfFile(FID);
    if (addDiagnosticsForContext(
            Correction, getIncludeFixerContext(
                            SM, CI->getPreprocessor().getHeaderSearchInfo(),
                            MatchedSymbols),
            Code, StartOfFile, CI->getASTContext()))
      return Correction;
  }
  return TypoCorrection();
}

/// Get the minimal include for a given path.
std::string IncludeFixerSemaSource::minimizeInclude(
    StringRef Include, const clang::SourceManager &SourceManager,
    clang::HeaderSearch &HeaderSearch) const {
  if (!MinimizeIncludePaths)
    return Include;

  // Get the FileEntry for the include.
  StringRef StrippedInclude = Include.trim("\"<>");
  const FileEntry *Entry =
      SourceManager.getFileManager().getFile(StrippedInclude);

  // If the file doesn't exist return the path from the database.
  // FIXME: This should never happen.
  if (!Entry)
    return Include;

  bool IsSystem;
  std::string Suggestion =
      HeaderSearch.suggestPathToFileForDiagnostics(Entry, &IsSystem);

  return IsSystem ? '<' + Suggestion + '>' : '"' + Suggestion + '"';
}

/// Get the include fixer context for the queried symbol.
IncludeFixerContext IncludeFixerSemaSource::getIncludeFixerContext(
    const clang::SourceManager &SourceManager,
    clang::HeaderSearch &HeaderSearch,
    ArrayRef<find_all_symbols::SymbolInfo> MatchedSymbols) const {
  std::vector<find_all_symbols::SymbolInfo> SymbolCandidates;
  for (const auto &Symbol : MatchedSymbols) {
    std::string FilePath = Symbol.getFilePath().str();
    std::string MinimizedFilePath = minimizeInclude(
        ((FilePath[0] == '"' || FilePath[0] == '<') ? FilePath
                                                    : "\"" + FilePath + "\""),
        SourceManager, HeaderSearch);
    SymbolCandidates.emplace_back(Symbol.getName(), Symbol.getSymbolKind(),
                                  MinimizedFilePath, Symbol.getContexts());
  }
  return IncludeFixerContext(FilePath, QuerySymbolInfos, SymbolCandidates);
}

std::vector<find_all_symbols::SymbolInfo>
IncludeFixerSemaSource::query(StringRef Query, StringRef ScopedQualifiers,
                              tooling::Range Range) {
  assert(!Query.empty() && "Empty query!");

  // Save all instances of an unidentified symbol.
  //
  // We use conservative behavior for detecting the same unidentified symbol
  // here. The symbols which have the same ScopedQualifier and RawIdentifier
  // are considered equal. So that include-fixer avoids false positives, and
  // always adds missing qualifiers to correct symbols.
  if (!GenerateDiagnostics && !QuerySymbolInfos.empty()) {
    if (ScopedQualifiers == QuerySymbolInfos.front().ScopedQualifiers &&
        Query == QuerySymbolInfos.front().RawIdentifier) {
      QuerySymbolInfos.push_back({Query.str(), ScopedQualifiers, Range});
    }
    return {};
  }

  LLVM_DEBUG(llvm::dbgs() << "Looking up '" << Query << "' at ");
  LLVM_DEBUG(CI->getSourceManager()
                 .getLocForStartOfFile(CI->getSourceManager().getMainFileID())
                 .getLocWithOffset(Range.getOffset())
                 .print(llvm::dbgs(), CI->getSourceManager()));
  LLVM_DEBUG(llvm::dbgs() << " ...");
  llvm::StringRef FileName = CI->getSourceManager().getFilename(
      CI->getSourceManager().getLocForStartOfFile(
          CI->getSourceManager().getMainFileID()));

  QuerySymbolInfos.push_back({Query.str(), ScopedQualifiers, Range});

  // Query the symbol based on C++ name Lookup rules.
  // Firstly, lookup the identifier with scoped namespace contexts;
  // If that fails, falls back to look up the identifier directly.
  //
  // For example:
  //
  // namespace a {
  // b::foo f;
  // }
  //
  // 1. lookup a::b::foo.
  // 2. lookup b::foo.
  std::string QueryString = ScopedQualifiers.str() + Query.str();
  // It's unsafe to do nested search for the identifier with scoped namespace
  // context, it might treat the identifier as a nested class of the scoped
  // namespace.
  std::vector<find_all_symbols::SymbolInfo> MatchedSymbols =
      SymbolIndexMgr.search(QueryString, /*IsNestedSearch=*/false, FileName);
  if (MatchedSymbols.empty())
    MatchedSymbols =
        SymbolIndexMgr.search(Query, /*IsNestedSearch=*/true, FileName);
  LLVM_DEBUG(llvm::dbgs() << "Having found " << MatchedSymbols.size()
                          << " symbols\n");
  // We store a copy of MatchedSymbols in a place where it's globally reachable.
  // This is used by the standalone version of the tool.
  this->MatchedSymbols = MatchedSymbols;
  return MatchedSymbols;
}

llvm::Expected<tooling::Replacements> createIncludeFixerReplacements(
    StringRef Code, const IncludeFixerContext &Context,
    const clang::format::FormatStyle &Style, bool AddQualifiers) {
  if (Context.getHeaderInfos().empty())
    return tooling::Replacements();
  StringRef FilePath = Context.getFilePath();
  std::string IncludeName =
      "#include " + Context.getHeaderInfos().front().Header + "\n";
  // Create replacements for the new header.
  clang::tooling::Replacements Insertions;
  auto Err =
      Insertions.add(tooling::Replacement(FilePath, UINT_MAX, 0, IncludeName));
  if (Err)
    return std::move(Err);

  auto CleanReplaces = cleanupAroundReplacements(Code, Insertions, Style);
  if (!CleanReplaces)
    return CleanReplaces;

  auto Replaces = std::move(*CleanReplaces);
  if (AddQualifiers) {
    for (const auto &Info : Context.getQuerySymbolInfos()) {
      // Ignore the empty range.
      if (Info.Range.getLength() > 0) {
        auto R = tooling::Replacement(
            {FilePath, Info.Range.getOffset(), Info.Range.getLength(),
             Context.getHeaderInfos().front().QualifiedName});
        auto Err = Replaces.add(R);
        if (Err) {
          llvm::consumeError(std::move(Err));
          R = tooling::Replacement(
              R.getFilePath(), Replaces.getShiftedCodePosition(R.getOffset()),
              R.getLength(), R.getReplacementText());
          Replaces = Replaces.merge(tooling::Replacements(R));
        }
      }
    }
  }
  return formatReplacements(Code, Replaces, Style);
}

} // namespace include_fixer
} // namespace clang
