// Part of the Crubit project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include "nullability/inference/eligible_ranges.h"

#include <algorithm>
#include <cassert>
#include <optional>
#include <string_view>
#include <utility>
#include <vector>

#include "absl/base/nullability.h"
#include "absl/log/check.h"
#include "nullability/inference/inferable.h"
#include "nullability/inference/inference.proto.h"
#include "nullability/type_nullability.h"
#include "third_party/llvm/llvm-project/clang-tools-extra/clang-tidy/utils/LexerUtils.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeLocVisitor.h"
#include "clang/Basic/FileEntry.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Index/USRGeneration.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Token.h"
#include "clang/Tooling/Transformer/SourceCode.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Path.h"

namespace clang::tidy::nullability {
namespace {
using SlotNum = unsigned;
}

static Nullability toProtoNullability(NullabilityKind Kind) {
  switch (Kind) {
    case NullabilityKind::NonNull:
      return Nullability::NONNULL;
    case NullabilityKind::Nullable:
    case NullabilityKind::NullableResult:
      return Nullability::NULLABLE;
    case NullabilityKind::Unspecified:
      return Nullability::UNKNOWN;
  }
  llvm_unreachable("Unhandled NullabilityKind");
}

static void initSlotRange(SlotRange &R, std::optional<SlotNum> Slot,
                          unsigned Begin, unsigned End,
                          std::optional<NullabilityKind> Nullability) {
  if (Slot) R.set_slot(*Slot);
  R.set_begin(Begin);
  R.set_end(End);
  if (Nullability) {
    R.set_existing_annotation(toProtoNullability(*Nullability));
  }
}

/// If the tokens immediately before `Begin` are an absl::NullabilityUnknown<
/// annotation start, returns the start location of the absl token. Else,
/// returns std::nullopt.
static std::pair<std::optional<unsigned>, std::optional<unsigned>>
getStartAndEndOffsetsOfImmediateAbslAnnotation(SourceLocation Begin,
                                               SourceLocation End,
                                               const SourceManager &SM,
                                               const LangOptions &LangOpts,
                                               const FileID &DeclFID) {
  // absl::NullabilityUnknown< is 4 tokens, one for the `<`, one for the `::`,
  // and one for each identifier.
  Token PrevTok = utils::lexer::getPreviousToken(Begin, SM, LangOpts);
  if (!PrevTok.is(tok::less)) return {};
  if (PrevTok =
          utils::lexer::getPreviousToken(PrevTok.getLocation(), SM, LangOpts);
      !PrevTok.is(tok::raw_identifier))
    return {};
  if (PrevTok.getRawIdentifier() != "NullabilityUnknown") return {};
  if (PrevTok =
          utils::lexer::getPreviousToken(PrevTok.getLocation(), SM, LangOpts);
      PrevTok.isNot(tok::coloncolon))
    return {};
  if (PrevTok =
          utils::lexer::getPreviousToken(PrevTok.getLocation(), SM, LangOpts);
      !PrevTok.is(tok::raw_identifier))
    return {};
  if (PrevTok.getRawIdentifier() != "absl") return {};

  auto [PrevTokFID, PrevTokOffset] = SM.getDecomposedLoc(PrevTok.getLocation());
  if (PrevTokFID != DeclFID) return {};

  Token NextTok;
  // If the token immediately at `End` is a `>`, use the end location of that
  // token. Otherwise, look for the next non-comment token, which should be a
  // `>`.
  if (bool Failed = Lexer::getRawToken(End, NextTok, SM, LangOpts,
                                       /*IgnoreWhiteSpace=*/true))
    return {};
  if (!NextTok.is(tok::greater) && !NextTok.is(tok::greatergreater)) {
    std::optional<Token> MaybeNextTok =
        utils::lexer::findNextTokenSkippingComments(End, SM, LangOpts);
    if (!MaybeNextTok || (!MaybeNextTok->is(tok::greater) &&
                          !MaybeNextTok->is(tok::greatergreater)))
      return {};
    NextTok = *MaybeNextTok;
  }

  auto [NextTokFID, NextTokOffset] = SM.getDecomposedLoc(NextTok.getEndLoc());
  if (NextTokFID != DeclFID) return {};
  if (NextTok.is(tok::greatergreater)) {
    // We need to step back one character.
    --NextTokOffset;
  }

  return {PrevTokOffset, NextTokOffset};
}

/// If the token immediately after `End` is a clang _Null_unspecified attribute,
/// returns the end location of the attribute. Else, returns std::nullopt.
static std::optional<unsigned> getEndOffsetOfImmediateClangAttribute(
    SourceLocation End, const SourceManager &SM, const LangOptions &LangOpts,
    const FileID &DeclFID) {
  // We can simply use `findNextTokenSkippingComments` because the attribute
  // must come at least one space or comment after the type, so it will come
  // after `End`, not at `End`.
  std::optional<Token> NextTok =
      utils::lexer::findNextTokenSkippingComments(End, SM, LangOpts);
  if (!NextTok) return std::nullopt;
  if (!NextTok->is(tok::raw_identifier) ||
      NextTok->getRawIdentifier() != "_Null_unspecified")
    return std::nullopt;

  auto [FID, Offset] = SM.getDecomposedLoc(NextTok->getEndLoc());
  if (FID != DeclFID) return std::nullopt;

  return Offset;
}

/// If the range specified by `Begin` and `End` is immediately wrapped in an
/// absl nullability annotation or immediately followed by a clang nullability
/// attribute, set the pre- and post-range lengths for that
/// annotation/attribute.
static void addAnnotationPreAndPostRangeLength(
    SourceLocation Begin, SourceLocation End, unsigned BeginOffset,
    unsigned EndOffset, const FileID &DeclFID, const SourceManager &SM,
    const LangOptions &LangOpts, SlotRange &Range) {
  auto [AnnotationStartOffset, AnnotationEndOffset] =
      getStartAndEndOffsetsOfImmediateAbslAnnotation(Begin, End, SM, LangOpts,
                                                     DeclFID);
  if (AnnotationStartOffset && AnnotationEndOffset) {
    Range.set_existing_annotation_pre_range_length(BeginOffset -
                                                   *AnnotationStartOffset);
    Range.set_existing_annotation_post_range_length(*AnnotationEndOffset -
                                                    EndOffset);
  } else if (std::optional<unsigned> AttributeEndOffset =
                 getEndOffsetOfImmediateClangAttribute(End, SM, LangOpts,
                                                       DeclFID)) {
    Range.set_existing_annotation_pre_range_length(0);
    Range.set_existing_annotation_post_range_length(*AttributeEndOffset -
                                                    EndOffset);
  }
}

/// Declarations involving combinations of pointers, arrays, and functions can
/// require re-arrangement of the type to add or remove nullability annotations.
///
/// The known relevant types are (potentially nested) raw pointers to arrays or
/// functions and (potentially nested) arrays of raw pointers.
///
/// e.g. a length-3 array of length-2 arrays of pointers to length-1 arrays of
/// int* with the name `p` would start as `int* (*p[3][2])[1]` and if we need to
/// mark the type of the pointers to the length-1 arrays Nullable, we would need
/// to re-write this is as `Nullable<int* (*)[1]> p[3][2]`.
///
/// Similarly, a function pointer with the name `f` with a single int*
/// parameter named `a` might start as `void(*f)(int* a)`. If we need to mark
/// the function pointer as Nullable, we would need to re-write this as
/// `Nullable<void(*)(int* a)> f`.
///
/// If Decl and its TypeLoc TL are such a declaration, returns a vector of
/// optional ComplexDeclaratorRanges, indexed by nullability slot in TL, to be
/// added to the corresponding SlotRange.
///
/// e.g. For `f` above, returns [{"f", [{7, 8}]}, std::nullopt]. For `p` above,
/// returns [{"p", [{8, 15}]}, std::nullopt]. And for `void (*(*(f))[])(int)`,
/// returns [{"(f)", [{10, 13}]}, {"(*)[]", [{8, 10}, {13, 16}]}].
///
/// The ranges are produced under the assumption that all slots will receive an
/// annotation. The types would need to be modified differently if e.g. some
/// inner slots are annotated but outer slots are not.
///
/// Template parameters are not considered, nor are smart pointers, so types
/// containing these may not have the correct number of results returned and the
/// results should not be used.
static std::vector<std::optional<ComplexDeclaratorRanges>>
getComplexDeclaratorRanges(const DeclaratorDecl &Decl, TypeLoc TL) {
  class Walker : public TypeLocVisitor<Walker> {
   public:
    std::vector<std::optional<ComplexDeclaratorRanges>> Results;

    Walker(const DeclaratorDecl &Decl)
        : SM(Decl.getASTContext().getSourceManager()), LO(Decl.getLangOpts()) {
      // Include any name for Decl in the range for the first slot.
      StartForSlot = Decl.getLocation();
      if (Decl.getDeclName().isEmpty()) {
        EndForSlot = StartForSlot;
      } else {
        std::optional<Token> NextTok =
            utils::lexer::findNextTokenSkippingComments(StartForSlot, SM, LO);
        if (NextTok) {
          EndForSlot = NextTok->getLocation();
        } else {
          EndForSlot = StartForSlot;
        }
      }
    }

    void Visit(TypeLoc TL) {
      // If the type ends before the start of the name, then Decl is not a
      // complex declarator.
      if (TL.getEndLoc() <= StartForSlot) {
        unsigned PointersInTL = countPointersInType(TL.getType());
        Results.reserve(PointersInTL);
        for (int I = 0; I < PointersInTL; ++I) Results.push_back(std::nullopt);
      } else {
        TypeLocVisitor::Visit(TL);
      }
    }

    void VisitTypeLoc(TypeLoc TL) {
      if (TL.getNextTypeLoc()) TypeLocVisitor::Visit(TL.getNextTypeLoc());
    }

    void VisitArrayTypeLoc(ArrayTypeLoc ArrayTL) {
      // Move the end marker to the right to include the array brackets,
      // including any size expression.
      EndForSlot = ArrayTL.getRBracketLoc().getLocWithOffset(1);
      Visit(ArrayTL.getElementLoc());
    }

    void VisitParenTypeLoc(ParenTypeLoc ParenTL) {
      StartForSlot = ParenTL.getLParenLoc();
      EndForSlot = ParenTL.getRParenLoc().getLocWithOffset(1);
      Visit(ParenTL.getInnerLoc());
    }

    void VisitPointerTypeLoc(PointerTypeLoc PointerTL) {
      if (StartForSlot == EndForSlot) {
        Results.push_back(std::nullopt);
      } else {
        // Save the result for the current slot.
        auto &Result = Results.emplace_back(ComplexDeclaratorRanges());
        if (StartForPreviousSlot && EndForPreviousSlot) {
          Result->set_following_annotation(
              (Lexer::getSourceText(clang::CharSourceRange::getCharRange(
                                        StartForSlot, *StartForPreviousSlot),
                                    SM, LO) +
               Lexer::getSourceText(clang::CharSourceRange::getCharRange(
                                        *EndForPreviousSlot, EndForSlot),
                                    SM, LO))
                  .str());

          if (StartForPreviousSlot != StartForSlot) {
            auto *Removal = Result->add_removal();
            Removal->set_begin(SM.getFileOffset(StartForSlot));
            Removal->set_end(SM.getFileOffset(*StartForPreviousSlot));
          }
          if (EndForPreviousSlot != EndForSlot) {
            auto *Removal = Result->add_removal();
            Removal->set_begin(SM.getFileOffset(*EndForPreviousSlot));
            Removal->set_end(SM.getFileOffset(EndForSlot));
          }
        } else {
          Result->set_following_annotation(Lexer::getSourceText(
              clang::CharSourceRange::getCharRange(StartForSlot, EndForSlot),
              SM, LO));
          auto &Removal = *Result->add_removal();
          Removal.set_begin(SM.getFileOffset(StartForSlot));
          Removal.set_end(SM.getFileOffset(EndForSlot));
        }
      }

      // Prepare for the next slot.
      StartForPreviousSlot = StartForSlot;
      EndForPreviousSlot = EndForSlot;

      // Move the begin marker to include the star to prepare for the next slot.
      StartForSlot = PointerTL.getStarLoc();

      Visit(PointerTL.getPointeeLoc());
    }

    void VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc FuncTL) {
      Visit(FuncTL.getReturnLoc());
      for (const auto &ParamDecl : FuncTL.getParams()) {
        if (auto *TSI = ParamDecl->getTypeSourceInfo()) {
          Walker Recurse(*ParamDecl);
          Recurse.Visit(TSI->getTypeLoc());
          for (const auto &Result : Recurse.Results) {
            Results.push_back(std::move(Result));
          }
        }
      }
    }

   private:
    const SourceManager &SM;
    const LangOptions &LO;
    SourceLocation StartForSlot;
    SourceLocation EndForSlot;
    std::optional<SourceLocation> StartForPreviousSlot;
    std::optional<SourceLocation> EndForPreviousSlot;
  };

  Walker W(Decl);
  W.Visit(TL);
  return std::move(W.Results);
}

// Extracts the source ranges and associated slot values of each eligible type
// within `Loc`, accounting for (nested) qualifiers. Guarantees that each source
// range is eligible for editing, including that its begin and end locations are
// in the same file.
//
// For each eligible TypeLoc, we do not consider the `const`-ness of the TypeLoc
// itself, because the edit will do the correct thing implicitly: the `const`
// will be left out of the TypeLoc's range, leaving `const` outside the
// nullability annotation, which is the preferred spelling.
static void addRangesQualifierAware(absl::Nullable<const DeclaratorDecl *> Decl,
                                    TypeLoc WholeLoc, SlotNum StartingSlot,
                                    const ASTContext &Context,
                                    const FileID &DeclFID,
                                    const TypeNullabilityDefaults &Defaults,
                                    TypeLocRanges &Result) {
  std::vector<TypeNullabilityLoc> NullabilityLocs =
      getTypeNullabilityLocs(WholeLoc, Defaults);
  std::vector<std::optional<ComplexDeclaratorRanges>>
      AllComplexDeclaratorRanges;
  if (Decl) {
    AllComplexDeclaratorRanges = getComplexDeclaratorRanges(*Decl, WholeLoc);
  }
  const auto &SM = Context.getSourceManager();
  const auto &LangOpts = Context.getLangOpts();
  for (auto &[SlotInLoc, T, MaybeLoc, Nullability] : NullabilityLocs) {
    if (!MaybeLoc || !isSupportedPointerType(MaybeLoc->getType())) continue;
    auto R = tooling::getFileRange(
        CharSourceRange::getTokenRange(MaybeLoc->getSourceRange()), Context,
        /*IncludeMacroExpansion=*/true);
    if (!R) continue;

    // The start of the new range.
    SourceLocation Begin = R->getBegin();

    // Update `Begin` as we search backwards and find qualifier tokens.
    auto PrevTok = utils::lexer::getPreviousToken(Begin, SM, LangOpts);
    while (PrevTok.getKind() != tok::unknown) {
      if (!PrevTok.is(tok::raw_identifier)) break;
      StringRef RawID = PrevTok.getRawIdentifier();
      if (RawID != "const" && RawID != "volatile" && RawID != "restrict") break;
      Begin = PrevTok.getLocation();
      PrevTok = utils::lexer::getPreviousToken(Begin, SM, LangOpts);
    }

    auto [FID, BeginOffset] = SM.getDecomposedLoc(Begin);
    // If the type comes from a different file, then don't attempt to edit -- it
    // might need manual intervention.
    if (FID != DeclFID) continue;

    unsigned EndOffset = SM.getFileOffset(R->getEnd());

    // TODO(b/323509132) When we can infer more than just top-level pointers,
    // synchronize these slot numbers with inference's slot numbers. For now,
    // assign no slot to anything but a first slot in an inferable type.
    std::optional<SlotNum> SlotInContext =
        SlotInLoc == 0 && hasInferable(WholeLoc.getType())
            ? std::optional(StartingSlot + SlotInLoc)
            : std::nullopt;

    SlotRange *Range = Result.add_range();
    initSlotRange(*Range, SlotInContext, BeginOffset, EndOffset, Nullability);
    if (Nullability && Nullability == NullabilityKind::Unspecified)
      addAnnotationPreAndPostRangeLength(Begin, R->getEnd(), BeginOffset,
                                         EndOffset, DeclFID, SM, LangOpts,
                                         *Range);

    // If we don't have a std::nullopt or ComplexDeclaratorRange for every slot,
    // don't add any ComplexDeclaratorRanges. The Decl is a complex declarator
    // but contains at least one unsupported slot syntax, such as slots in
    // template parameters or smart pointers.
    if (Decl && AllComplexDeclaratorRanges.size() == NullabilityLocs.size()) {
      CHECK(AllComplexDeclaratorRanges.size() > SlotInLoc);
      std::optional<ComplexDeclaratorRanges> &CDR =
          AllComplexDeclaratorRanges[SlotInLoc];
      // If all removal ranges are after the end of the range to enclose in the
      // annotation, then we don't need to add any ComplexDeclaratorRanges and
      // can leave the text where it is.
      if (CDR && std::any_of(CDR->removal().begin(), CDR->removal().end(),
                             [EndOffset](const RemovalRange &Removal) {
                               return Removal.begin() < EndOffset;
                             })) {
        *Range->mutable_complex_declarator_ranges() = std::move(*CDR);
      }
    }
  }
}

static bool trySetPath(FileID FID, const SourceManager &SrcMgr,
                       TypeLocRanges &Ranges) {
  const clang::OptionalFileEntryRef Entry = SrcMgr.getFileEntryRefForID(FID);
  if (!Entry) return false;
  Ranges.set_path(std::string_view(
      llvm::sys::path::remove_leading_dotslash(Entry->getName())));
  return true;
}

static void setPragmaNullability(FileID FID,
                                 const TypeNullabilityDefaults &Defaults,
                                 TypeLocRanges &Ranges) {
  // Don't use Defaults.get(File) in order to avoid treating a lack of pragma as
  // a pragma setting of Defaults.DefaultNullability.
  if (!Defaults.FileNullability) return;
  if (auto It = Defaults.FileNullability->find(FID);
      It != Defaults.FileNullability->end()) {
    Ranges.set_pragma_nullability(toProtoNullability(It->second));
  }
}

static std::optional<TypeLocRanges> getEligibleRanges(
    const FunctionDecl &Fun, const TypeNullabilityDefaults &Defaults) {
  FunctionTypeLoc TyLoc = Fun.getFunctionTypeLoc();
  if (TyLoc.isNull()) return std::nullopt;
  const clang::ASTContext &Context = Fun.getParentASTContext();
  const SourceManager &SrcMgr = Context.getSourceManager();
  FileID DeclFID = SrcMgr.getFileID(SrcMgr.getExpansionLoc(Fun.getLocation()));
  if (!DeclFID.isValid()) return std::nullopt;

  TypeLocRanges Result;
  if (!trySetPath(DeclFID, SrcMgr, Result)) return std::nullopt;
  setPragmaNullability(DeclFID, Defaults, Result);

  addRangesQualifierAware(nullptr, TyLoc.getReturnLoc(), SLOT_RETURN_TYPE,
                          Context, DeclFID, Defaults, Result);

  for (int I = 0, N = Fun.getNumParams(); I < N; ++I) {
    const ParmVarDecl *P = Fun.getParamDecl(I);
    addRangesQualifierAware(P, P->getTypeSourceInfo()->getTypeLoc(),
                            SLOT_PARAM + I, Context, DeclFID, Defaults, Result);
  }

  if (Result.range().empty()) return std::nullopt;

  return Result;
}

static std::optional<TypeLocRanges> getEligibleRanges(
    const DeclaratorDecl &D, const TypeNullabilityDefaults &Defaults) {
  TypeLoc TyLoc = D.getTypeSourceInfo()->getTypeLoc();
  if (TyLoc.isNull()) return std::nullopt;
  const clang::ASTContext &Context = D.getASTContext();
  const SourceManager &SrcMgr = Context.getSourceManager();
  FileID DeclFID = SrcMgr.getFileID(SrcMgr.getExpansionLoc(D.getLocation()));
  if (!DeclFID.isValid()) return std::nullopt;

  TypeLocRanges Result;
  if (!trySetPath(DeclFID, SrcMgr, Result)) return std::nullopt;
  setPragmaNullability(DeclFID, Defaults, Result);

  addRangesQualifierAware(&D, TyLoc, Slot(0), Context, DeclFID, Defaults,
                          Result);
  if (Result.range().empty()) return std::nullopt;

  return Result;
}

std::optional<TypeLocRanges> getEligibleRanges(
    const Decl &D, const TypeNullabilityDefaults &Defaults) {
  if (const auto *Fun = clang::dyn_cast<FunctionDecl>(&D))
    return getEligibleRanges(*Fun, Defaults);
  if (const auto *Field = clang::dyn_cast<FieldDecl>(&D))
    return getEligibleRanges(*Field, Defaults);
  if (const auto *Var = clang::dyn_cast<VarDecl>(&D))
    return getEligibleRanges(*Var, Defaults);
  return std::nullopt;
}

std::optional<TypeLocRanges> getInferenceRanges(
    const Decl &D, const TypeNullabilityDefaults &Defaults) {
  if (!isInferenceTarget(D)) return std::nullopt;
  return getEligibleRanges(D, Defaults);
}

}  // namespace clang::tidy::nullability
