/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file LICENSE.rst or https://cmake.org/licensing for details.  */

/* This code was originally taken from part of the Clang-Tidy LLVM project and
 * modified for use with CMake under the following original license: */

//===--- HeaderGuard.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 "UsePragmaOnceCheck.h"

#include <algorithm>
#include <cassert>

#include <clang/Frontend/CompilerInstance.h>
#include <clang/Lex/PPCallbacks.h>
#include <clang/Lex/Preprocessor.h>
#include <clang/Tooling/Tooling.h>
#include <llvm/Support/Path.h>

namespace clang {
namespace tidy {
namespace cmake {

/// canonicalize a path by removing ./ and ../ components.
static std::string cleanPath(StringRef Path)
{
  SmallString<256> Result = Path;
  llvm::sys::path::remove_dots(Result, true);
  return std::string(Result.str());
}

namespace {
// This class is a workaround for the fact that PPCallbacks doesn't give us the
// location of the hash for an #ifndef, #define, or #endif, so we have to find
// it ourselves. We can't lex backwards, and attempting to turn on the
// preprocessor's backtracking functionality wreaks havoc, so we have to
// instantiate a second lexer and lex all the way from the beginning of the
// file. Cache the results of this lexing so that we don't have to do it more
// times than needed.
//
// TODO: Upstream a change to LLVM to give us the location of the hash in
// PPCallbacks so we don't have to do this workaround.
class DirectiveCache
{
public:
  DirectiveCache(Preprocessor* PP, FileID FID)
    : PP(PP)
    , FID(FID)
  {
    SourceManager& SM = this->PP->getSourceManager();
    OptionalFileEntryRef Entry = SM.getFileEntryRefForID(FID);
    assert(Entry && "Invalid FileID given");

    Lexer MyLexer(FID, SM.getMemoryBufferForFileOrFake(*Entry), SM,
                  this->PP->getLangOpts());
    Token Tok;

    while (!MyLexer.LexFromRawLexer(Tok)) {
      if (Tok.getKind() == tok::hash) {
        assert(SM.getFileID(Tok.getLocation()) == this->FID &&
               "Token FileID does not match passed FileID");
        if (!this->HashLocs.empty()) {
          assert(SM.getFileOffset(this->HashLocs.back()) <
                   SM.getFileOffset(Tok.getLocation()) &&
                 "Tokens in file are not in order");
        }

        this->HashLocs.push_back(Tok.getLocation());
      }
    }
  }

  SourceRange createRangeForIfndef(SourceLocation IfndefMacroTokLoc)
  {
    // The #ifndef of an include guard is likely near the beginning of the
    // file, so search from the front.
    return SourceRange(this->findPreviousHashFromFront(IfndefMacroTokLoc),
                       IfndefMacroTokLoc);
  }

  SourceRange createRangeForDefine(SourceLocation DefineMacroTokLoc)
  {
    // The #define of an include guard is likely near the beginning of the
    // file, so search from the front.
    return SourceRange(this->findPreviousHashFromFront(DefineMacroTokLoc),
                       DefineMacroTokLoc);
  }

  SourceRange createRangeForEndif(SourceLocation EndifLoc)
  {
    // The #endif of an include guard is likely near the end of the file, so
    // search from the back.
    return SourceRange(this->findPreviousHashFromBack(EndifLoc), EndifLoc);
  }

private:
  Preprocessor* PP;
  FileID FID;
  SmallVector<SourceLocation> HashLocs;

  SourceLocation findPreviousHashFromFront(SourceLocation Loc)
  {
    SourceManager& SM = this->PP->getSourceManager();
    Loc = SM.getExpansionLoc(Loc);
    assert(SM.getFileID(Loc) == this->FID &&
           "Loc FileID does not match our FileID");

    auto It = std::find_if(
      this->HashLocs.begin(), this->HashLocs.end(),
      [&SM, &Loc](SourceLocation const& OtherLoc) -> bool {
        return SM.getFileOffset(OtherLoc) >= SM.getFileOffset(Loc);
      });
    assert(It != this->HashLocs.begin() &&
           "No hash associated with passed Loc");
    return *--It;
  }

  SourceLocation findPreviousHashFromBack(SourceLocation Loc)
  {
    SourceManager& SM = this->PP->getSourceManager();
    Loc = SM.getExpansionLoc(Loc);
    assert(SM.getFileID(Loc) == this->FID &&
           "Loc FileID does not match our FileID");

    auto It =
      std::find_if(this->HashLocs.rbegin(), this->HashLocs.rend(),
                   [&SM, &Loc](SourceLocation const& OtherLoc) -> bool {
                     return SM.getFileOffset(OtherLoc) < SM.getFileOffset(Loc);
                   });
    assert(It != this->HashLocs.rend() &&
           "No hash associated with passed Loc");
    return *It;
  }
};

class UsePragmaOncePPCallbacks : public PPCallbacks
{
public:
  UsePragmaOncePPCallbacks(Preprocessor* PP, UsePragmaOnceCheck* Check)
    : PP(PP)
    , Check(Check)
  {
  }

  void FileChanged(SourceLocation Loc, FileChangeReason Reason,
                   SrcMgr::CharacteristicKind FileType,
                   FileID PrevFID) override
  {
    // Record all files we enter. We'll need them to diagnose headers without
    // guards.
    SourceManager& SM = this->PP->getSourceManager();
    if (Reason == EnterFile && FileType == SrcMgr::C_User) {
      if (OptionalFileEntryRef FE =
            SM.getFileEntryRefForID(SM.getFileID(Loc))) {
        std::string FileName = cleanPath(FE->getName());
        this->Files.try_emplace(FileName, *FE);
      }
    }
  }

  void Ifndef(SourceLocation Loc, Token const& MacroNameTok,
              MacroDefinition const& MD) override
  {
    if (MD) {
      return;
    }

    // Record #ifndefs that succeeded. We also need the Location of the Name.
    this->Ifndefs[MacroNameTok.getIdentifierInfo()] =
      std::make_pair(Loc, MacroNameTok.getLocation());
  }

  void MacroDefined(Token const& MacroNameTok,
                    MacroDirective const* MD) override
  {
    // Record all defined macros. We store the whole token to get info on the
    // name later.
    this->Macros.emplace_back(MacroNameTok, MD->getMacroInfo());
  }

  void Endif(SourceLocation Loc, SourceLocation IfLoc) override
  {
    // Record all #endif and the corresponding #ifs (including #ifndefs).
    this->EndIfs[IfLoc] = Loc;
  }

  void EndOfMainFile() override
  {
    // Now that we have all this information from the preprocessor, use it!
    SourceManager& SM = this->PP->getSourceManager();

    for (auto const& MacroEntry : this->Macros) {
      MacroInfo const* MI = MacroEntry.second;

      // We use clang's header guard detection. This has the advantage of also
      // emitting a warning for cases where a pseudo header guard is found but
      // preceded by something blocking the header guard optimization.
      if (!MI->isUsedForHeaderGuard()) {
        continue;
      }

      FileEntryRef FE =
        *SM.getFileEntryRefForID(SM.getFileID(MI->getDefinitionLoc()));
      std::string FileName = cleanPath(FE.getName());
      this->Files.erase(FileName);

      // Look up Locations for this guard.
      SourceLocation Ifndef =
        this->Ifndefs[MacroEntry.first.getIdentifierInfo()].second;
      SourceLocation Define = MacroEntry.first.getLocation();
      SourceLocation EndIf =
        this
          ->EndIfs[this->Ifndefs[MacroEntry.first.getIdentifierInfo()].first];

      std::vector<FixItHint> FixIts;

      HeaderSearch& HeaderInfo = this->PP->getHeaderSearchInfo();

      HeaderFileInfo& Info = HeaderInfo.getFileInfo(FE);

      DirectiveCache Cache(this->PP, SM.getFileID(MI->getDefinitionLoc()));
      SourceRange IfndefSrcRange = Cache.createRangeForIfndef(Ifndef);
      SourceRange DefineSrcRange = Cache.createRangeForDefine(Define);
      SourceRange EndifSrcRange = Cache.createRangeForEndif(EndIf);

      if (Info.isPragmaOnce) {
        FixIts.push_back(FixItHint::CreateRemoval(IfndefSrcRange));
      } else {
        FixIts.push_back(
          FixItHint::CreateReplacement(IfndefSrcRange, "#pragma once"));
      }

      FixIts.push_back(FixItHint::CreateRemoval(DefineSrcRange));
      FixIts.push_back(FixItHint::CreateRemoval(EndifSrcRange));

      this->Check->diag(IfndefSrcRange.getBegin(), "use #pragma once")
        << FixIts;
    }

    // Emit warnings for headers that are missing guards.
    checkGuardlessHeaders();
    clearAllState();
  }

  /// Looks for files that were visited but didn't have a header guard.
  /// Emits a warning with fixits suggesting adding one.
  void checkGuardlessHeaders()
  {
    // Look for header files that didn't have a header guard. Emit a warning
    // and fix-its to add the guard.
    // TODO: Insert the guard after top comments.
    for (auto const& FE : this->Files) {
      StringRef FileName = FE.getKey();
      if (!Check->shouldSuggestToAddPragmaOnce(FileName)) {
        continue;
      }

      SourceManager& SM = this->PP->getSourceManager();
      FileID FID = SM.translateFile(FE.getValue());
      SourceLocation StartLoc = SM.getLocForStartOfFile(FID);
      if (StartLoc.isInvalid()) {
        continue;
      }

      HeaderSearch& HeaderInfo = this->PP->getHeaderSearchInfo();

      HeaderFileInfo& Info = HeaderInfo.getFileInfo(FE.second);
      if (Info.isPragmaOnce) {
        continue;
      }

      this->Check->diag(StartLoc, "use #pragma once")
        << FixItHint::CreateInsertion(StartLoc, "#pragma once\n");
    }
  }

private:
  void clearAllState()
  {
    this->Macros.clear();
    this->Files.clear();
    this->Ifndefs.clear();
    this->EndIfs.clear();
  }

  std::vector<std::pair<Token, MacroInfo const*>> Macros;
  llvm::StringMap<FileEntryRef> Files;
  std::map<IdentifierInfo const*, std::pair<SourceLocation, SourceLocation>>
    Ifndefs;
  std::map<SourceLocation, SourceLocation> EndIfs;

  Preprocessor* PP;
  UsePragmaOnceCheck* Check;
};
} // namespace

void UsePragmaOnceCheck::storeOptions(ClangTidyOptions::OptionMap& Opts)
{
  this->Options.store(Opts, "HeaderFileExtensions",
                      RawStringHeaderFileExtensions);
}

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

bool UsePragmaOnceCheck::shouldSuggestToAddPragmaOnce(StringRef FileName)
{
  return utils::isFileExtension(FileName, this->HeaderFileExtensions);
}

} // namespace cmake
} // namespace tidy
} // namespace clang
