//===- AnalyzerOptions.cpp - Analysis Engine Options ----------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file contains special accessors for analyzer configuration options
// with string representations.
//
//===----------------------------------------------------------------------===//

#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cstddef>
#include <utility>
#include <vector>

using namespace clang;
using namespace ento;
using namespace llvm;

void AnalyzerOptions::printFormattedEntry(
    llvm::raw_ostream &Out,
    std::pair<StringRef, StringRef> EntryDescPair,
    size_t InitialPad, size_t EntryWidth, size_t MinLineWidth) {

  llvm::formatted_raw_ostream FOut(Out);

  const size_t PadForDesc = InitialPad + EntryWidth;

  FOut.PadToColumn(InitialPad) << EntryDescPair.first;
  // If the buffer's length is greater then PadForDesc, print a newline.
  if (FOut.getColumn() > PadForDesc)
    FOut << '\n';

  FOut.PadToColumn(PadForDesc);

  if (MinLineWidth == 0) {
    FOut << EntryDescPair.second;
    return;
  }

  for (char C : EntryDescPair.second) {
    if (FOut.getColumn() > MinLineWidth && C == ' ') {
      FOut << '\n';
      FOut.PadToColumn(PadForDesc);
      continue;
    }
    FOut << C;
  }
}

ExplorationStrategyKind
AnalyzerOptions::getExplorationStrategy() const {
  auto K =
    llvm::StringSwitch<llvm::Optional<ExplorationStrategyKind>>(
                                                            ExplorationStrategy)
          .Case("dfs", ExplorationStrategyKind::DFS)
          .Case("bfs", ExplorationStrategyKind::BFS)
          .Case("unexplored_first",
                ExplorationStrategyKind::UnexploredFirst)
          .Case("unexplored_first_queue",
                ExplorationStrategyKind::UnexploredFirstQueue)
          .Case("unexplored_first_location_queue",
                ExplorationStrategyKind::UnexploredFirstLocationQueue)
          .Case("bfs_block_dfs_contents",
                ExplorationStrategyKind::BFSBlockDFSContents)
          .Default(None);
  assert(K.hasValue() && "User mode is invalid.");
  return K.getValue();
}

IPAKind AnalyzerOptions::getIPAMode() const {
  auto K = llvm::StringSwitch<llvm::Optional<IPAKind>>(IPAMode)
          .Case("none", IPAK_None)
          .Case("basic-inlining", IPAK_BasicInlining)
          .Case("inlining", IPAK_Inlining)
          .Case("dynamic", IPAK_DynamicDispatch)
          .Case("dynamic-bifurcate", IPAK_DynamicDispatchBifurcate)
          .Default(None);
  assert(K.hasValue() && "IPA Mode is invalid.");

  return K.getValue();
}

bool
AnalyzerOptions::mayInlineCXXMemberFunction(
                                          CXXInlineableMemberKind Param) const {
  if (getIPAMode() < IPAK_Inlining)
    return false;

  auto K =
    llvm::StringSwitch<llvm::Optional<CXXInlineableMemberKind>>(
                                                          CXXMemberInliningMode)
    .Case("constructors", CIMK_Constructors)
    .Case("destructors", CIMK_Destructors)
    .Case("methods", CIMK_MemberFunctions)
    .Case("none", CIMK_None)
    .Default(None);

  assert(K.hasValue() && "Invalid c++ member function inlining mode.");

  return *K >= Param;
}

StringRef AnalyzerOptions::getCheckerStringOption(StringRef CheckerName,
                                                  StringRef OptionName,
                                                  bool SearchInParents) const {
  assert(!CheckerName.empty() &&
         "Empty checker name! Make sure the checker object (including it's "
         "bases!) if fully initialized before calling this function!");

  ConfigTable::const_iterator E = Config.end();
  do {
    ConfigTable::const_iterator I =
        Config.find((Twine(CheckerName) + ":" + OptionName).str());
    if (I != E)
      return StringRef(I->getValue());
    size_t Pos = CheckerName.rfind('.');
    if (Pos == StringRef::npos)
      break;

    CheckerName = CheckerName.substr(0, Pos);
  } while (!CheckerName.empty() && SearchInParents);

  llvm_unreachable("Unknown checker option! Did you call getChecker*Option "
                   "with incorrect parameters? User input must've been "
                   "verified by CheckerRegistry.");

  return "";
}

StringRef AnalyzerOptions::getCheckerStringOption(const ento::CheckerBase *C,
                                                  StringRef OptionName,
                                                  bool SearchInParents) const {
  return getCheckerStringOption(
                           C->getTagDescription(), OptionName, SearchInParents);
}

bool AnalyzerOptions::getCheckerBooleanOption(StringRef CheckerName,
                                              StringRef OptionName,
                                              bool SearchInParents) const {
  auto Ret = llvm::StringSwitch<llvm::Optional<bool>>(
      getCheckerStringOption(CheckerName, OptionName,
                             SearchInParents))
      .Case("true", true)
      .Case("false", false)
      .Default(None);

  assert(Ret &&
         "This option should be either 'true' or 'false', and should've been "
         "validated by CheckerRegistry!");

  return *Ret;
}

bool AnalyzerOptions::getCheckerBooleanOption(const ento::CheckerBase *C,
                                              StringRef OptionName,
                                              bool SearchInParents) const {
  return getCheckerBooleanOption(
             C->getTagDescription(), OptionName, SearchInParents);
}

int AnalyzerOptions::getCheckerIntegerOption(StringRef CheckerName,
                                             StringRef OptionName,
                                             bool SearchInParents) const {
  int Ret = 0;
  bool HasFailed = getCheckerStringOption(CheckerName, OptionName,
                                          SearchInParents)
                     .getAsInteger(0, Ret);
  assert(!HasFailed &&
         "This option should be numeric, and should've been validated by "
         "CheckerRegistry!");
  (void)HasFailed;
  return Ret;
}

int AnalyzerOptions::getCheckerIntegerOption(const ento::CheckerBase *C,
                                             StringRef OptionName,
                                             bool SearchInParents) const {
  return getCheckerIntegerOption(
                           C->getTagDescription(), OptionName, SearchInParents);
}
