//===--- IncludeOrderCheck.cpp - clang-tidy -------------------------------===//
//
// 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 "IncludeOrderCheck.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/STLExtras.h"

#include <map>

namespace clang::tidy::llvm_check {

namespace {
class IncludeOrderPPCallbacks : public PPCallbacks {
public:
  explicit IncludeOrderPPCallbacks(ClangTidyCheck &Check,
                                   const SourceManager &SM)
      : LookForMainModule(true), Check(Check), SM(SM) {}

  void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
                          StringRef FileName, bool IsAngled,
                          CharSourceRange FilenameRange,
                          OptionalFileEntryRef File, StringRef SearchPath,
                          StringRef RelativePath, const Module *Imported,
                          SrcMgr::CharacteristicKind FileType) override;
  void EndOfMainFile() override;

private:
  struct IncludeDirective {
    SourceLocation Loc;    ///< '#' location in the include directive
    CharSourceRange Range; ///< SourceRange for the file name
    std::string Filename;  ///< Filename as a string
    bool IsAngled;         ///< true if this was an include with angle brackets
    bool IsMainModule;     ///< true if this was the first include in a file
  };

  typedef std::vector<IncludeDirective> FileIncludes;
  std::map<clang::FileID, FileIncludes> IncludeDirectives;
  bool LookForMainModule;

  ClangTidyCheck &Check;
  const SourceManager &SM;
};
} // namespace

void IncludeOrderCheck::registerPPCallbacks(const SourceManager &SM,
                                            Preprocessor *PP,
                                            Preprocessor *ModuleExpanderPP) {
  PP->addPPCallbacks(::std::make_unique<IncludeOrderPPCallbacks>(*this, SM));
}

static int getPriority(StringRef Filename, bool IsAngled, bool IsMainModule) {
  // We leave the main module header at the top.
  if (IsMainModule)
    return 0;

  // LLVM and clang headers are in the penultimate position.
  if (Filename.startswith("llvm/") || Filename.startswith("llvm-c/") ||
      Filename.startswith("clang/") || Filename.startswith("clang-c/"))
    return 2;

  // Put these between system and llvm headers to be consistent with LLVM
  // clang-format style.
  if (Filename.startswith("gtest/") || Filename.startswith("gmock/"))
    return 3;

  // System headers are sorted to the end.
  if (IsAngled)
    return 4;

  // Other headers are inserted between the main module header and LLVM headers.
  return 1;
}

void IncludeOrderPPCallbacks::InclusionDirective(
    SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
    bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File,
    StringRef SearchPath, StringRef RelativePath, const Module *Imported,
    SrcMgr::CharacteristicKind FileType) {
  // We recognize the first include as a special main module header and want
  // to leave it in the top position.
  IncludeDirective ID = {HashLoc, FilenameRange, std::string(FileName),
                         IsAngled, false};
  if (LookForMainModule && !IsAngled) {
    ID.IsMainModule = true;
    LookForMainModule = false;
  }

  // Bucket the include directives by the id of the file they were declared in.
  IncludeDirectives[SM.getFileID(HashLoc)].push_back(std::move(ID));
}

void IncludeOrderPPCallbacks::EndOfMainFile() {
  LookForMainModule = true;
  if (IncludeDirectives.empty())
    return;

  // TODO: find duplicated includes.

  // Form blocks of includes. We don't want to sort across blocks. This also
  // implicitly makes us never reorder over #defines or #if directives.
  // FIXME: We should be more careful about sorting below comments as we don't
  // know if the comment refers to the next include or the whole block that
  // follows.
  for (auto &Bucket : IncludeDirectives) {
    auto &FileDirectives = Bucket.second;
    std::vector<unsigned> Blocks(1, 0);
    for (unsigned I = 1, E = FileDirectives.size(); I != E; ++I)
      if (SM.getExpansionLineNumber(FileDirectives[I].Loc) !=
          SM.getExpansionLineNumber(FileDirectives[I - 1].Loc) + 1)
        Blocks.push_back(I);
    Blocks.push_back(FileDirectives.size()); // Sentinel value.

    // Get a vector of indices.
    std::vector<unsigned> IncludeIndices;
    for (unsigned I = 0, E = FileDirectives.size(); I != E; ++I)
      IncludeIndices.push_back(I);

    // Sort the includes. We first sort by priority, then lexicographically.
    for (unsigned BI = 0, BE = Blocks.size() - 1; BI != BE; ++BI)
      llvm::sort(IncludeIndices.begin() + Blocks[BI],
                 IncludeIndices.begin() + Blocks[BI + 1],
                 [&FileDirectives](unsigned LHSI, unsigned RHSI) {
                   IncludeDirective &LHS = FileDirectives[LHSI];
                   IncludeDirective &RHS = FileDirectives[RHSI];

                   int PriorityLHS = getPriority(LHS.Filename, LHS.IsAngled,
                                                 LHS.IsMainModule);
                   int PriorityRHS = getPriority(RHS.Filename, RHS.IsAngled,
                                                 RHS.IsMainModule);

                   return std::tie(PriorityLHS, LHS.Filename) <
                          std::tie(PriorityRHS, RHS.Filename);
                 });

    // Emit a warning for each block and fixits for all changes within that
    // block.
    for (unsigned BI = 0, BE = Blocks.size() - 1; BI != BE; ++BI) {
      // Find the first include that's not in the right position.
      unsigned I, E;
      for (I = Blocks[BI], E = Blocks[BI + 1]; I != E; ++I)
        if (IncludeIndices[I] != I)
          break;

      if (I == E)
        continue;

      // Emit a warning.
      auto D = Check.diag(FileDirectives[I].Loc,
                          "#includes are not sorted properly");

      // Emit fix-its for all following includes in this block.
      for (; I != E; ++I) {
        if (IncludeIndices[I] == I)
          continue;
        const IncludeDirective &CopyFrom = FileDirectives[IncludeIndices[I]];

        SourceLocation FromLoc = CopyFrom.Range.getBegin();
        const char *FromData = SM.getCharacterData(FromLoc);
        unsigned FromLen = std::strcspn(FromData, "\n");

        StringRef FixedName(FromData, FromLen);

        SourceLocation ToLoc = FileDirectives[I].Range.getBegin();
        const char *ToData = SM.getCharacterData(ToLoc);
        unsigned ToLen = std::strcspn(ToData, "\n");
        auto ToRange =
            CharSourceRange::getCharRange(ToLoc, ToLoc.getLocWithOffset(ToLen));

        D << FixItHint::CreateReplacement(ToRange, FixedName);
      }
    }
  }

  IncludeDirectives.clear();
}

} // namespace clang::tidy::llvm_check
