//===--- CommentSema.cpp - Doxygen comment semantic analysis --------------===//
//
// 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 "clang/AST/CommentSema.h"
#include "clang/AST/Attr.h"
#include "clang/AST/CommentCommandTraits.h"
#include "clang/AST/CommentDiagnostic.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"

namespace clang {
namespace comments {

namespace {
#include "clang/AST/CommentHTMLTagsProperties.inc"
} // end anonymous namespace

Sema::Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr,
           DiagnosticsEngine &Diags, CommandTraits &Traits,
           const Preprocessor *PP) :
    Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags), Traits(Traits),
    PP(PP), ThisDeclInfo(nullptr), BriefCommand(nullptr),
    HeaderfileCommand(nullptr) {
}

void Sema::setDecl(const Decl *D) {
  if (!D)
    return;

  ThisDeclInfo = new (Allocator) DeclInfo;
  ThisDeclInfo->CommentDecl = D;
  ThisDeclInfo->IsFilled = false;
}

ParagraphComment *Sema::actOnParagraphComment(
                              ArrayRef<InlineContentComment *> Content) {
  return new (Allocator) ParagraphComment(Content);
}

BlockCommandComment *Sema::actOnBlockCommandStart(
                                      SourceLocation LocBegin,
                                      SourceLocation LocEnd,
                                      unsigned CommandID,
                                      CommandMarkerKind CommandMarker) {
  BlockCommandComment *BC = new (Allocator) BlockCommandComment(LocBegin, LocEnd,
                                                                CommandID,
                                                                CommandMarker);
  checkContainerDecl(BC);
  return BC;
}

void Sema::actOnBlockCommandArgs(BlockCommandComment *Command,
                                 ArrayRef<BlockCommandComment::Argument> Args) {
  Command->setArgs(Args);
}

void Sema::actOnBlockCommandFinish(BlockCommandComment *Command,
                                   ParagraphComment *Paragraph) {
  Command->setParagraph(Paragraph);
  checkBlockCommandEmptyParagraph(Command);
  checkBlockCommandDuplicate(Command);
  if (ThisDeclInfo) {
    // These checks only make sense if the comment is attached to a
    // declaration.
    checkReturnsCommand(Command);
    checkDeprecatedCommand(Command);
  }
}

ParamCommandComment *Sema::actOnParamCommandStart(
                                      SourceLocation LocBegin,
                                      SourceLocation LocEnd,
                                      unsigned CommandID,
                                      CommandMarkerKind CommandMarker) {
  ParamCommandComment *Command =
      new (Allocator) ParamCommandComment(LocBegin, LocEnd, CommandID,
                                          CommandMarker);

  if (!isFunctionDecl() && !isFunctionOrBlockPointerVarLikeDecl())
    Diag(Command->getLocation(),
         diag::warn_doc_param_not_attached_to_a_function_decl)
      << CommandMarker
      << Command->getCommandNameRange(Traits);

  return Command;
}

void Sema::checkFunctionDeclVerbatimLine(const BlockCommandComment *Comment) {
  const CommandInfo *Info = Traits.getCommandInfo(Comment->getCommandID());
  if (!Info->IsFunctionDeclarationCommand)
    return;

  unsigned DiagSelect;
  switch (Comment->getCommandID()) {
    case CommandTraits::KCI_function:
      DiagSelect = (!isAnyFunctionDecl() && !isFunctionTemplateDecl())? 1 : 0;
      break;
    case CommandTraits::KCI_functiongroup:
      DiagSelect = (!isAnyFunctionDecl() && !isFunctionTemplateDecl())? 2 : 0;
      break;
    case CommandTraits::KCI_method:
      DiagSelect = !isObjCMethodDecl() ? 3 : 0;
      break;
    case CommandTraits::KCI_methodgroup:
      DiagSelect = !isObjCMethodDecl() ? 4 : 0;
      break;
    case CommandTraits::KCI_callback:
      DiagSelect = !isFunctionPointerVarDecl() ? 5 : 0;
      break;
    default:
      DiagSelect = 0;
      break;
  }
  if (DiagSelect)
    Diag(Comment->getLocation(), diag::warn_doc_function_method_decl_mismatch)
    << Comment->getCommandMarker()
    << (DiagSelect-1) << (DiagSelect-1)
    << Comment->getSourceRange();
}

void Sema::checkContainerDeclVerbatimLine(const BlockCommandComment *Comment) {
  const CommandInfo *Info = Traits.getCommandInfo(Comment->getCommandID());
  if (!Info->IsRecordLikeDeclarationCommand)
    return;
  unsigned DiagSelect;
  switch (Comment->getCommandID()) {
    case CommandTraits::KCI_class:
      DiagSelect = (!isClassOrStructDecl() && !isClassTemplateDecl()) ? 1 : 0;
      // Allow @class command on @interface declarations.
      // FIXME. Currently, \class and @class are indistinguishable. So,
      // \class is also allowed on an @interface declaration
      if (DiagSelect && Comment->getCommandMarker() && isObjCInterfaceDecl())
        DiagSelect = 0;
      break;
    case CommandTraits::KCI_interface:
      DiagSelect = !isObjCInterfaceDecl() ? 2 : 0;
      break;
    case CommandTraits::KCI_protocol:
      DiagSelect = !isObjCProtocolDecl() ? 3 : 0;
      break;
    case CommandTraits::KCI_struct:
      DiagSelect = !isClassOrStructDecl() ? 4 : 0;
      break;
    case CommandTraits::KCI_union:
      DiagSelect = !isUnionDecl() ? 5 : 0;
      break;
    default:
      DiagSelect = 0;
      break;
  }
  if (DiagSelect)
    Diag(Comment->getLocation(), diag::warn_doc_api_container_decl_mismatch)
    << Comment->getCommandMarker()
    << (DiagSelect-1) << (DiagSelect-1)
    << Comment->getSourceRange();
}

void Sema::checkContainerDecl(const BlockCommandComment *Comment) {
  const CommandInfo *Info = Traits.getCommandInfo(Comment->getCommandID());
  if (!Info->IsRecordLikeDetailCommand || isRecordLikeDecl())
    return;
  unsigned DiagSelect;
  switch (Comment->getCommandID()) {
    case CommandTraits::KCI_classdesign:
      DiagSelect = 1;
      break;
    case CommandTraits::KCI_coclass:
      DiagSelect = 2;
      break;
    case CommandTraits::KCI_dependency:
      DiagSelect = 3;
      break;
    case CommandTraits::KCI_helper:
      DiagSelect = 4;
      break;
    case CommandTraits::KCI_helperclass:
      DiagSelect = 5;
      break;
    case CommandTraits::KCI_helps:
      DiagSelect = 6;
      break;
    case CommandTraits::KCI_instancesize:
      DiagSelect = 7;
      break;
    case CommandTraits::KCI_ownership:
      DiagSelect = 8;
      break;
    case CommandTraits::KCI_performance:
      DiagSelect = 9;
      break;
    case CommandTraits::KCI_security:
      DiagSelect = 10;
      break;
    case CommandTraits::KCI_superclass:
      DiagSelect = 11;
      break;
    default:
      DiagSelect = 0;
      break;
  }
  if (DiagSelect)
    Diag(Comment->getLocation(), diag::warn_doc_container_decl_mismatch)
    << Comment->getCommandMarker()
    << (DiagSelect-1)
    << Comment->getSourceRange();
}

/// Turn a string into the corresponding PassDirection or -1 if it's not
/// valid.
static int getParamPassDirection(StringRef Arg) {
  return llvm::StringSwitch<int>(Arg)
      .Case("[in]", ParamCommandComment::In)
      .Case("[out]", ParamCommandComment::Out)
      .Cases("[in,out]", "[out,in]", ParamCommandComment::InOut)
      .Default(-1);
}

void Sema::actOnParamCommandDirectionArg(ParamCommandComment *Command,
                                         SourceLocation ArgLocBegin,
                                         SourceLocation ArgLocEnd,
                                         StringRef Arg) {
  std::string ArgLower = Arg.lower();
  int Direction = getParamPassDirection(ArgLower);

  if (Direction == -1) {
    // Try again with whitespace removed.
    ArgLower.erase(
        std::remove_if(ArgLower.begin(), ArgLower.end(), clang::isWhitespace),
        ArgLower.end());
    Direction = getParamPassDirection(ArgLower);

    SourceRange ArgRange(ArgLocBegin, ArgLocEnd);
    if (Direction != -1) {
      const char *FixedName = ParamCommandComment::getDirectionAsString(
          (ParamCommandComment::PassDirection)Direction);
      Diag(ArgLocBegin, diag::warn_doc_param_spaces_in_direction)
          << ArgRange << FixItHint::CreateReplacement(ArgRange, FixedName);
    } else {
      Diag(ArgLocBegin, diag::warn_doc_param_invalid_direction) << ArgRange;
      Direction = ParamCommandComment::In; // Sane fall back.
    }
  }
  Command->setDirection((ParamCommandComment::PassDirection)Direction,
                        /*Explicit=*/true);
}

void Sema::actOnParamCommandParamNameArg(ParamCommandComment *Command,
                                         SourceLocation ArgLocBegin,
                                         SourceLocation ArgLocEnd,
                                         StringRef Arg) {
  // Parser will not feed us more arguments than needed.
  assert(Command->getNumArgs() == 0);

  if (!Command->isDirectionExplicit()) {
    // User didn't provide a direction argument.
    Command->setDirection(ParamCommandComment::In, /* Explicit = */ false);
  }
  typedef BlockCommandComment::Argument Argument;
  Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin,
                                                     ArgLocEnd),
                                         Arg);
  Command->setArgs(llvm::makeArrayRef(A, 1));
}

void Sema::actOnParamCommandFinish(ParamCommandComment *Command,
                                   ParagraphComment *Paragraph) {
  Command->setParagraph(Paragraph);
  checkBlockCommandEmptyParagraph(Command);
}

TParamCommandComment *Sema::actOnTParamCommandStart(
                                      SourceLocation LocBegin,
                                      SourceLocation LocEnd,
                                      unsigned CommandID,
                                      CommandMarkerKind CommandMarker) {
  TParamCommandComment *Command =
      new (Allocator) TParamCommandComment(LocBegin, LocEnd, CommandID,
                                           CommandMarker);

  if (!isTemplateOrSpecialization())
    Diag(Command->getLocation(),
         diag::warn_doc_tparam_not_attached_to_a_template_decl)
      << CommandMarker
      << Command->getCommandNameRange(Traits);

  return Command;
}

void Sema::actOnTParamCommandParamNameArg(TParamCommandComment *Command,
                                          SourceLocation ArgLocBegin,
                                          SourceLocation ArgLocEnd,
                                          StringRef Arg) {
  // Parser will not feed us more arguments than needed.
  assert(Command->getNumArgs() == 0);

  typedef BlockCommandComment::Argument Argument;
  Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin,
                                                     ArgLocEnd),
                                         Arg);
  Command->setArgs(llvm::makeArrayRef(A, 1));

  if (!isTemplateOrSpecialization()) {
    // We already warned that this \\tparam is not attached to a template decl.
    return;
  }

  const TemplateParameterList *TemplateParameters =
      ThisDeclInfo->TemplateParameters;
  SmallVector<unsigned, 2> Position;
  if (resolveTParamReference(Arg, TemplateParameters, &Position)) {
    Command->setPosition(copyArray(llvm::makeArrayRef(Position)));
    TParamCommandComment *&PrevCommand = TemplateParameterDocs[Arg];
    if (PrevCommand) {
      SourceRange ArgRange(ArgLocBegin, ArgLocEnd);
      Diag(ArgLocBegin, diag::warn_doc_tparam_duplicate)
        << Arg << ArgRange;
      Diag(PrevCommand->getLocation(), diag::note_doc_tparam_previous)
        << PrevCommand->getParamNameRange();
    }
    PrevCommand = Command;
    return;
  }

  SourceRange ArgRange(ArgLocBegin, ArgLocEnd);
  Diag(ArgLocBegin, diag::warn_doc_tparam_not_found)
    << Arg << ArgRange;

  if (!TemplateParameters || TemplateParameters->size() == 0)
    return;

  StringRef CorrectedName;
  if (TemplateParameters->size() == 1) {
    const NamedDecl *Param = TemplateParameters->getParam(0);
    const IdentifierInfo *II = Param->getIdentifier();
    if (II)
      CorrectedName = II->getName();
  } else {
    CorrectedName = correctTypoInTParamReference(Arg, TemplateParameters);
  }

  if (!CorrectedName.empty()) {
    Diag(ArgLocBegin, diag::note_doc_tparam_name_suggestion)
      << CorrectedName
      << FixItHint::CreateReplacement(ArgRange, CorrectedName);
  }
}

void Sema::actOnTParamCommandFinish(TParamCommandComment *Command,
                                    ParagraphComment *Paragraph) {
  Command->setParagraph(Paragraph);
  checkBlockCommandEmptyParagraph(Command);
}

InlineCommandComment *Sema::actOnInlineCommand(SourceLocation CommandLocBegin,
                                               SourceLocation CommandLocEnd,
                                               unsigned CommandID) {
  ArrayRef<InlineCommandComment::Argument> Args;
  StringRef CommandName = Traits.getCommandInfo(CommandID)->Name;
  return new (Allocator) InlineCommandComment(
                                  CommandLocBegin,
                                  CommandLocEnd,
                                  CommandID,
                                  getInlineCommandRenderKind(CommandName),
                                  Args);
}

InlineCommandComment *Sema::actOnInlineCommand(SourceLocation CommandLocBegin,
                                               SourceLocation CommandLocEnd,
                                               unsigned CommandID,
                                               SourceLocation ArgLocBegin,
                                               SourceLocation ArgLocEnd,
                                               StringRef Arg) {
  typedef InlineCommandComment::Argument Argument;
  Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin,
                                                     ArgLocEnd),
                                         Arg);
  StringRef CommandName = Traits.getCommandInfo(CommandID)->Name;

  return new (Allocator) InlineCommandComment(
                                  CommandLocBegin,
                                  CommandLocEnd,
                                  CommandID,
                                  getInlineCommandRenderKind(CommandName),
                                  llvm::makeArrayRef(A, 1));
}

InlineContentComment *Sema::actOnUnknownCommand(SourceLocation LocBegin,
                                                SourceLocation LocEnd,
                                                StringRef CommandName) {
  unsigned CommandID = Traits.registerUnknownCommand(CommandName)->getID();
  return actOnUnknownCommand(LocBegin, LocEnd, CommandID);
}

InlineContentComment *Sema::actOnUnknownCommand(SourceLocation LocBegin,
                                                SourceLocation LocEnd,
                                                unsigned CommandID) {
  ArrayRef<InlineCommandComment::Argument> Args;
  return new (Allocator) InlineCommandComment(
                                  LocBegin, LocEnd, CommandID,
                                  InlineCommandComment::RenderNormal,
                                  Args);
}

TextComment *Sema::actOnText(SourceLocation LocBegin,
                             SourceLocation LocEnd,
                             StringRef Text) {
  return new (Allocator) TextComment(LocBegin, LocEnd, Text);
}

VerbatimBlockComment *Sema::actOnVerbatimBlockStart(SourceLocation Loc,
                                                    unsigned CommandID) {
  StringRef CommandName = Traits.getCommandInfo(CommandID)->Name;
  return new (Allocator) VerbatimBlockComment(
                                  Loc,
                                  Loc.getLocWithOffset(1 + CommandName.size()),
                                  CommandID);
}

VerbatimBlockLineComment *Sema::actOnVerbatimBlockLine(SourceLocation Loc,
                                                       StringRef Text) {
  return new (Allocator) VerbatimBlockLineComment(Loc, Text);
}

void Sema::actOnVerbatimBlockFinish(
                            VerbatimBlockComment *Block,
                            SourceLocation CloseNameLocBegin,
                            StringRef CloseName,
                            ArrayRef<VerbatimBlockLineComment *> Lines) {
  Block->setCloseName(CloseName, CloseNameLocBegin);
  Block->setLines(Lines);
}

VerbatimLineComment *Sema::actOnVerbatimLine(SourceLocation LocBegin,
                                             unsigned CommandID,
                                             SourceLocation TextBegin,
                                             StringRef Text) {
  VerbatimLineComment *VL = new (Allocator) VerbatimLineComment(
                              LocBegin,
                              TextBegin.getLocWithOffset(Text.size()),
                              CommandID,
                              TextBegin,
                              Text);
  checkFunctionDeclVerbatimLine(VL);
  checkContainerDeclVerbatimLine(VL);
  return VL;
}

HTMLStartTagComment *Sema::actOnHTMLStartTagStart(SourceLocation LocBegin,
                                                  StringRef TagName) {
  return new (Allocator) HTMLStartTagComment(LocBegin, TagName);
}

void Sema::actOnHTMLStartTagFinish(
                              HTMLStartTagComment *Tag,
                              ArrayRef<HTMLStartTagComment::Attribute> Attrs,
                              SourceLocation GreaterLoc,
                              bool IsSelfClosing) {
  Tag->setAttrs(Attrs);
  Tag->setGreaterLoc(GreaterLoc);
  if (IsSelfClosing)
    Tag->setSelfClosing();
  else if (!isHTMLEndTagForbidden(Tag->getTagName()))
    HTMLOpenTags.push_back(Tag);
}

HTMLEndTagComment *Sema::actOnHTMLEndTag(SourceLocation LocBegin,
                                         SourceLocation LocEnd,
                                         StringRef TagName) {
  HTMLEndTagComment *HET =
      new (Allocator) HTMLEndTagComment(LocBegin, LocEnd, TagName);
  if (isHTMLEndTagForbidden(TagName)) {
    Diag(HET->getLocation(), diag::warn_doc_html_end_forbidden)
      << TagName << HET->getSourceRange();
    HET->setIsMalformed();
    return HET;
  }

  bool FoundOpen = false;
  for (SmallVectorImpl<HTMLStartTagComment *>::const_reverse_iterator
       I = HTMLOpenTags.rbegin(), E = HTMLOpenTags.rend();
       I != E; ++I) {
    if ((*I)->getTagName() == TagName) {
      FoundOpen = true;
      break;
    }
  }
  if (!FoundOpen) {
    Diag(HET->getLocation(), diag::warn_doc_html_end_unbalanced)
      << HET->getSourceRange();
    HET->setIsMalformed();
    return HET;
  }

  while (!HTMLOpenTags.empty()) {
    HTMLStartTagComment *HST = HTMLOpenTags.pop_back_val();
    StringRef LastNotClosedTagName = HST->getTagName();
    if (LastNotClosedTagName == TagName) {
      // If the start tag is malformed, end tag is malformed as well.
      if (HST->isMalformed())
        HET->setIsMalformed();
      break;
    }

    if (isHTMLEndTagOptional(LastNotClosedTagName))
      continue;

    bool OpenLineInvalid;
    const unsigned OpenLine = SourceMgr.getPresumedLineNumber(
                                                HST->getLocation(),
                                                &OpenLineInvalid);
    bool CloseLineInvalid;
    const unsigned CloseLine = SourceMgr.getPresumedLineNumber(
                                                HET->getLocation(),
                                                &CloseLineInvalid);

    if (OpenLineInvalid || CloseLineInvalid || OpenLine == CloseLine) {
      Diag(HST->getLocation(), diag::warn_doc_html_start_end_mismatch)
        << HST->getTagName() << HET->getTagName()
        << HST->getSourceRange() << HET->getSourceRange();
      HST->setIsMalformed();
    } else {
      Diag(HST->getLocation(), diag::warn_doc_html_start_end_mismatch)
        << HST->getTagName() << HET->getTagName()
        << HST->getSourceRange();
      Diag(HET->getLocation(), diag::note_doc_html_end_tag)
        << HET->getSourceRange();
      HST->setIsMalformed();
    }
  }

  return HET;
}

FullComment *Sema::actOnFullComment(
                              ArrayRef<BlockContentComment *> Blocks) {
  FullComment *FC = new (Allocator) FullComment(Blocks, ThisDeclInfo);
  resolveParamCommandIndexes(FC);

  // Complain about HTML tags that are not closed.
  while (!HTMLOpenTags.empty()) {
    HTMLStartTagComment *HST = HTMLOpenTags.pop_back_val();
    if (isHTMLEndTagOptional(HST->getTagName()))
      continue;

    Diag(HST->getLocation(), diag::warn_doc_html_missing_end_tag)
      << HST->getTagName() << HST->getSourceRange();
    HST->setIsMalformed();
  }

  return FC;
}

void Sema::checkBlockCommandEmptyParagraph(BlockCommandComment *Command) {
  if (Traits.getCommandInfo(Command->getCommandID())->IsEmptyParagraphAllowed)
    return;

  ParagraphComment *Paragraph = Command->getParagraph();
  if (Paragraph->isWhitespace()) {
    SourceLocation DiagLoc;
    if (Command->getNumArgs() > 0)
      DiagLoc = Command->getArgRange(Command->getNumArgs() - 1).getEnd();
    if (!DiagLoc.isValid())
      DiagLoc = Command->getCommandNameRange(Traits).getEnd();
    Diag(DiagLoc, diag::warn_doc_block_command_empty_paragraph)
      << Command->getCommandMarker()
      << Command->getCommandName(Traits)
      << Command->getSourceRange();
  }
}

void Sema::checkReturnsCommand(const BlockCommandComment *Command) {
  if (!Traits.getCommandInfo(Command->getCommandID())->IsReturnsCommand)
    return;

  assert(ThisDeclInfo && "should not call this check on a bare comment");

  // We allow the return command for all @properties because it can be used
  // to document the value that the property getter returns.
  if (isObjCPropertyDecl())
    return;
  if (isFunctionDecl() || isFunctionOrBlockPointerVarLikeDecl()) {
    assert(!ThisDeclInfo->ReturnType.isNull() &&
           "should have a valid return type");
    if (ThisDeclInfo->ReturnType->isVoidType()) {
      unsigned DiagKind;
      switch (ThisDeclInfo->CommentDecl->getKind()) {
      default:
        if (ThisDeclInfo->IsObjCMethod)
          DiagKind = 3;
        else
          DiagKind = 0;
        break;
      case Decl::CXXConstructor:
        DiagKind = 1;
        break;
      case Decl::CXXDestructor:
        DiagKind = 2;
        break;
      }
      Diag(Command->getLocation(),
           diag::warn_doc_returns_attached_to_a_void_function)
        << Command->getCommandMarker()
        << Command->getCommandName(Traits)
        << DiagKind
        << Command->getSourceRange();
    }
    return;
  }

  Diag(Command->getLocation(),
       diag::warn_doc_returns_not_attached_to_a_function_decl)
    << Command->getCommandMarker()
    << Command->getCommandName(Traits)
    << Command->getSourceRange();
}

void Sema::checkBlockCommandDuplicate(const BlockCommandComment *Command) {
  const CommandInfo *Info = Traits.getCommandInfo(Command->getCommandID());
  const BlockCommandComment *PrevCommand = nullptr;
  if (Info->IsBriefCommand) {
    if (!BriefCommand) {
      BriefCommand = Command;
      return;
    }
    PrevCommand = BriefCommand;
  } else if (Info->IsHeaderfileCommand) {
    if (!HeaderfileCommand) {
      HeaderfileCommand = Command;
      return;
    }
    PrevCommand = HeaderfileCommand;
  } else {
    // We don't want to check this command for duplicates.
    return;
  }
  StringRef CommandName = Command->getCommandName(Traits);
  StringRef PrevCommandName = PrevCommand->getCommandName(Traits);
  Diag(Command->getLocation(), diag::warn_doc_block_command_duplicate)
      << Command->getCommandMarker()
      << CommandName
      << Command->getSourceRange();
  if (CommandName == PrevCommandName)
    Diag(PrevCommand->getLocation(), diag::note_doc_block_command_previous)
        << PrevCommand->getCommandMarker()
        << PrevCommandName
        << PrevCommand->getSourceRange();
  else
    Diag(PrevCommand->getLocation(),
         diag::note_doc_block_command_previous_alias)
        << PrevCommand->getCommandMarker()
        << PrevCommandName
        << CommandName;
}

void Sema::checkDeprecatedCommand(const BlockCommandComment *Command) {
  if (!Traits.getCommandInfo(Command->getCommandID())->IsDeprecatedCommand)
    return;

  assert(ThisDeclInfo && "should not call this check on a bare comment");

  const Decl *D = ThisDeclInfo->CommentDecl;
  if (!D)
    return;

  if (D->hasAttr<DeprecatedAttr>() ||
      D->hasAttr<AvailabilityAttr>() ||
      D->hasAttr<UnavailableAttr>())
    return;

  Diag(Command->getLocation(), diag::warn_doc_deprecated_not_sync)
      << Command->getSourceRange() << Command->getCommandMarker();

  // Try to emit a fixit with a deprecation attribute.
  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
    // Don't emit a Fix-It for non-member function definitions.  GCC does not
    // accept attributes on them.
    const DeclContext *Ctx = FD->getDeclContext();
    if ((!Ctx || !Ctx->isRecord()) &&
        FD->doesThisDeclarationHaveABody())
      return;

    const LangOptions &LO = FD->getASTContext().getLangOpts();
    const bool DoubleSquareBracket = LO.CPlusPlus14 || LO.C2x;
    StringRef AttributeSpelling =
        DoubleSquareBracket ? "[[deprecated]]" : "__attribute__((deprecated))";
    if (PP) {
      // Try to find a replacement macro:
      // - In C2x/C++14 we prefer [[deprecated]].
      // - If not found or an older C/C++ look for __attribute__((deprecated)).
      StringRef MacroName;
      if (DoubleSquareBracket) {
        TokenValue Tokens[] = {tok::l_square, tok::l_square,
                               PP->getIdentifierInfo("deprecated"),
                               tok::r_square, tok::r_square};
        MacroName = PP->getLastMacroWithSpelling(FD->getLocation(), Tokens);
        if (!MacroName.empty())
          AttributeSpelling = MacroName;
      }

      if (MacroName.empty()) {
        TokenValue Tokens[] = {
            tok::kw___attribute, tok::l_paren,
            tok::l_paren,        PP->getIdentifierInfo("deprecated"),
            tok::r_paren,        tok::r_paren};
        StringRef MacroName =
            PP->getLastMacroWithSpelling(FD->getLocation(), Tokens);
        if (!MacroName.empty())
          AttributeSpelling = MacroName;
      }
    }

    SmallString<64> TextToInsert = AttributeSpelling;
    TextToInsert += " ";
    SourceLocation Loc = FD->getSourceRange().getBegin();
    Diag(Loc, diag::note_add_deprecation_attr)
        << FixItHint::CreateInsertion(Loc, TextToInsert);
  }
}

void Sema::resolveParamCommandIndexes(const FullComment *FC) {
  if (!isFunctionDecl()) {
    // We already warned that \\param commands are not attached to a function
    // decl.
    return;
  }

  SmallVector<ParamCommandComment *, 8> UnresolvedParamCommands;

  // Comment AST nodes that correspond to \c ParamVars for which we have
  // found a \\param command or NULL if no documentation was found so far.
  SmallVector<ParamCommandComment *, 8> ParamVarDocs;

  ArrayRef<const ParmVarDecl *> ParamVars = getParamVars();
  ParamVarDocs.resize(ParamVars.size(), nullptr);

  // First pass over all \\param commands: resolve all parameter names.
  for (Comment::child_iterator I = FC->child_begin(), E = FC->child_end();
       I != E; ++I) {
    ParamCommandComment *PCC = dyn_cast<ParamCommandComment>(*I);
    if (!PCC || !PCC->hasParamName())
      continue;
    StringRef ParamName = PCC->getParamNameAsWritten();

    // Check that referenced parameter name is in the function decl.
    const unsigned ResolvedParamIndex = resolveParmVarReference(ParamName,
                                                                ParamVars);
    if (ResolvedParamIndex == ParamCommandComment::VarArgParamIndex) {
      PCC->setIsVarArgParam();
      continue;
    }
    if (ResolvedParamIndex == ParamCommandComment::InvalidParamIndex) {
      UnresolvedParamCommands.push_back(PCC);
      continue;
    }
    PCC->setParamIndex(ResolvedParamIndex);
    if (ParamVarDocs[ResolvedParamIndex]) {
      SourceRange ArgRange = PCC->getParamNameRange();
      Diag(ArgRange.getBegin(), diag::warn_doc_param_duplicate)
        << ParamName << ArgRange;
      ParamCommandComment *PrevCommand = ParamVarDocs[ResolvedParamIndex];
      Diag(PrevCommand->getLocation(), diag::note_doc_param_previous)
        << PrevCommand->getParamNameRange();
    }
    ParamVarDocs[ResolvedParamIndex] = PCC;
  }

  // Find parameter declarations that have no corresponding \\param.
  SmallVector<const ParmVarDecl *, 8> OrphanedParamDecls;
  for (unsigned i = 0, e = ParamVarDocs.size(); i != e; ++i) {
    if (!ParamVarDocs[i])
      OrphanedParamDecls.push_back(ParamVars[i]);
  }

  // Second pass over unresolved \\param commands: do typo correction.
  // Suggest corrections from a set of parameter declarations that have no
  // corresponding \\param.
  for (unsigned i = 0, e = UnresolvedParamCommands.size(); i != e; ++i) {
    const ParamCommandComment *PCC = UnresolvedParamCommands[i];

    SourceRange ArgRange = PCC->getParamNameRange();
    StringRef ParamName = PCC->getParamNameAsWritten();
    Diag(ArgRange.getBegin(), diag::warn_doc_param_not_found)
      << ParamName << ArgRange;

    // All parameters documented -- can't suggest a correction.
    if (OrphanedParamDecls.size() == 0)
      continue;

    unsigned CorrectedParamIndex = ParamCommandComment::InvalidParamIndex;
    if (OrphanedParamDecls.size() == 1) {
      // If one parameter is not documented then that parameter is the only
      // possible suggestion.
      CorrectedParamIndex = 0;
    } else {
      // Do typo correction.
      CorrectedParamIndex = correctTypoInParmVarReference(ParamName,
                                                          OrphanedParamDecls);
    }
    if (CorrectedParamIndex != ParamCommandComment::InvalidParamIndex) {
      const ParmVarDecl *CorrectedPVD = OrphanedParamDecls[CorrectedParamIndex];
      if (const IdentifierInfo *CorrectedII = CorrectedPVD->getIdentifier())
        Diag(ArgRange.getBegin(), diag::note_doc_param_name_suggestion)
          << CorrectedII->getName()
          << FixItHint::CreateReplacement(ArgRange, CorrectedII->getName());
    }
  }
}

bool Sema::isFunctionDecl() {
  if (!ThisDeclInfo)
    return false;
  if (!ThisDeclInfo->IsFilled)
    inspectThisDecl();
  return ThisDeclInfo->getKind() == DeclInfo::FunctionKind;
}

bool Sema::isAnyFunctionDecl() {
  return isFunctionDecl() && ThisDeclInfo->CurrentDecl &&
         isa<FunctionDecl>(ThisDeclInfo->CurrentDecl);
}

bool Sema::isFunctionOrMethodVariadic() {
  if (!isFunctionDecl() || !ThisDeclInfo->CurrentDecl)
    return false;
  if (const FunctionDecl *FD =
        dyn_cast<FunctionDecl>(ThisDeclInfo->CurrentDecl))
    return FD->isVariadic();
  if (const FunctionTemplateDecl *FTD =
        dyn_cast<FunctionTemplateDecl>(ThisDeclInfo->CurrentDecl))
    return FTD->getTemplatedDecl()->isVariadic();
  if (const ObjCMethodDecl *MD =
        dyn_cast<ObjCMethodDecl>(ThisDeclInfo->CurrentDecl))
    return MD->isVariadic();
  if (const TypedefNameDecl *TD =
          dyn_cast<TypedefNameDecl>(ThisDeclInfo->CurrentDecl)) {
    QualType Type = TD->getUnderlyingType();
    if (Type->isFunctionPointerType() || Type->isBlockPointerType())
      Type = Type->getPointeeType();
    if (const auto *FT = Type->getAs<FunctionProtoType>())
      return FT->isVariadic();
  }
  return false;
}

bool Sema::isObjCMethodDecl() {
  return isFunctionDecl() && ThisDeclInfo->CurrentDecl &&
         isa<ObjCMethodDecl>(ThisDeclInfo->CurrentDecl);
}

bool Sema::isFunctionPointerVarDecl() {
  if (!ThisDeclInfo)
    return false;
  if (!ThisDeclInfo->IsFilled)
    inspectThisDecl();
  if (ThisDeclInfo->getKind() == DeclInfo::VariableKind) {
    if (const VarDecl *VD = dyn_cast_or_null<VarDecl>(ThisDeclInfo->CurrentDecl)) {
      QualType QT = VD->getType();
      return QT->isFunctionPointerType();
    }
  }
  return false;
}

bool Sema::isFunctionOrBlockPointerVarLikeDecl() {
  if (!ThisDeclInfo)
    return false;
  if (!ThisDeclInfo->IsFilled)
    inspectThisDecl();
  if (ThisDeclInfo->getKind() != DeclInfo::VariableKind ||
      !ThisDeclInfo->CurrentDecl)
    return false;
  QualType QT;
  if (const auto *VD = dyn_cast<DeclaratorDecl>(ThisDeclInfo->CurrentDecl))
    QT = VD->getType();
  else if (const auto *PD =
               dyn_cast<ObjCPropertyDecl>(ThisDeclInfo->CurrentDecl))
    QT = PD->getType();
  else
    return false;
  // We would like to warn about the 'returns'/'param' commands for
  // variables that don't directly specify the function type, so type aliases
  // can be ignored.
  if (QT->getAs<TypedefType>())
    return false;
  if (const auto *P = QT->getAs<PointerType>())
    if (P->getPointeeType()->getAs<TypedefType>())
      return false;
  if (const auto *P = QT->getAs<BlockPointerType>())
    if (P->getPointeeType()->getAs<TypedefType>())
      return false;
  return QT->isFunctionPointerType() || QT->isBlockPointerType();
}

bool Sema::isObjCPropertyDecl() {
  if (!ThisDeclInfo)
    return false;
  if (!ThisDeclInfo->IsFilled)
    inspectThisDecl();
  return ThisDeclInfo->CurrentDecl->getKind() == Decl::ObjCProperty;
}

bool Sema::isTemplateOrSpecialization() {
  if (!ThisDeclInfo)
    return false;
  if (!ThisDeclInfo->IsFilled)
    inspectThisDecl();
  return ThisDeclInfo->getTemplateKind() != DeclInfo::NotTemplate;
}

bool Sema::isRecordLikeDecl() {
  if (!ThisDeclInfo)
    return false;
  if (!ThisDeclInfo->IsFilled)
    inspectThisDecl();
  return isUnionDecl() || isClassOrStructDecl() || isObjCInterfaceDecl() ||
         isObjCProtocolDecl();
}

bool Sema::isUnionDecl() {
  if (!ThisDeclInfo)
    return false;
  if (!ThisDeclInfo->IsFilled)
    inspectThisDecl();
  if (const RecordDecl *RD =
        dyn_cast_or_null<RecordDecl>(ThisDeclInfo->CurrentDecl))
    return RD->isUnion();
  return false;
}

bool Sema::isClassOrStructDecl() {
  if (!ThisDeclInfo)
    return false;
  if (!ThisDeclInfo->IsFilled)
    inspectThisDecl();
  return ThisDeclInfo->CurrentDecl &&
         isa<RecordDecl>(ThisDeclInfo->CurrentDecl) &&
         !isUnionDecl();
}

bool Sema::isClassTemplateDecl() {
  if (!ThisDeclInfo)
    return false;
  if (!ThisDeclInfo->IsFilled)
    inspectThisDecl();
  return ThisDeclInfo->CurrentDecl &&
          (isa<ClassTemplateDecl>(ThisDeclInfo->CurrentDecl));
}

bool Sema::isFunctionTemplateDecl() {
  if (!ThisDeclInfo)
    return false;
  if (!ThisDeclInfo->IsFilled)
    inspectThisDecl();
  return ThisDeclInfo->CurrentDecl &&
         (isa<FunctionTemplateDecl>(ThisDeclInfo->CurrentDecl));
}

bool Sema::isObjCInterfaceDecl() {
  if (!ThisDeclInfo)
    return false;
  if (!ThisDeclInfo->IsFilled)
    inspectThisDecl();
  return ThisDeclInfo->CurrentDecl &&
         isa<ObjCInterfaceDecl>(ThisDeclInfo->CurrentDecl);
}

bool Sema::isObjCProtocolDecl() {
  if (!ThisDeclInfo)
    return false;
  if (!ThisDeclInfo->IsFilled)
    inspectThisDecl();
  return ThisDeclInfo->CurrentDecl &&
         isa<ObjCProtocolDecl>(ThisDeclInfo->CurrentDecl);
}

ArrayRef<const ParmVarDecl *> Sema::getParamVars() {
  if (!ThisDeclInfo->IsFilled)
    inspectThisDecl();
  return ThisDeclInfo->ParamVars;
}

void Sema::inspectThisDecl() {
  ThisDeclInfo->fill();
}

unsigned Sema::resolveParmVarReference(StringRef Name,
                                       ArrayRef<const ParmVarDecl *> ParamVars) {
  for (unsigned i = 0, e = ParamVars.size(); i != e; ++i) {
    const IdentifierInfo *II = ParamVars[i]->getIdentifier();
    if (II && II->getName() == Name)
      return i;
  }
  if (Name == "..." && isFunctionOrMethodVariadic())
    return ParamCommandComment::VarArgParamIndex;
  return ParamCommandComment::InvalidParamIndex;
}

namespace {
class SimpleTypoCorrector {
  const NamedDecl *BestDecl;

  StringRef Typo;
  const unsigned MaxEditDistance;

  unsigned BestEditDistance;
  unsigned BestIndex;
  unsigned NextIndex;

public:
  explicit SimpleTypoCorrector(StringRef Typo)
      : BestDecl(nullptr), Typo(Typo), MaxEditDistance((Typo.size() + 2) / 3),
        BestEditDistance(MaxEditDistance + 1), BestIndex(0), NextIndex(0) {}

  void addDecl(const NamedDecl *ND);

  const NamedDecl *getBestDecl() const {
    if (BestEditDistance > MaxEditDistance)
      return nullptr;

    return BestDecl;
  }

  unsigned getBestDeclIndex() const {
    assert(getBestDecl());
    return BestIndex;
  }
};

void SimpleTypoCorrector::addDecl(const NamedDecl *ND) {
  unsigned CurrIndex = NextIndex++;

  const IdentifierInfo *II = ND->getIdentifier();
  if (!II)
    return;

  StringRef Name = II->getName();
  unsigned MinPossibleEditDistance = abs((int)Name.size() - (int)Typo.size());
  if (MinPossibleEditDistance > 0 &&
      Typo.size() / MinPossibleEditDistance < 3)
    return;

  unsigned EditDistance = Typo.edit_distance(Name, true, MaxEditDistance);
  if (EditDistance < BestEditDistance) {
    BestEditDistance = EditDistance;
    BestDecl = ND;
    BestIndex = CurrIndex;
  }
}
} // end anonymous namespace

unsigned Sema::correctTypoInParmVarReference(
                                    StringRef Typo,
                                    ArrayRef<const ParmVarDecl *> ParamVars) {
  SimpleTypoCorrector Corrector(Typo);
  for (unsigned i = 0, e = ParamVars.size(); i != e; ++i)
    Corrector.addDecl(ParamVars[i]);
  if (Corrector.getBestDecl())
    return Corrector.getBestDeclIndex();
  else
    return ParamCommandComment::InvalidParamIndex;
}

namespace {
bool ResolveTParamReferenceHelper(
                            StringRef Name,
                            const TemplateParameterList *TemplateParameters,
                            SmallVectorImpl<unsigned> *Position) {
  for (unsigned i = 0, e = TemplateParameters->size(); i != e; ++i) {
    const NamedDecl *Param = TemplateParameters->getParam(i);
    const IdentifierInfo *II = Param->getIdentifier();
    if (II && II->getName() == Name) {
      Position->push_back(i);
      return true;
    }

    if (const TemplateTemplateParmDecl *TTP =
            dyn_cast<TemplateTemplateParmDecl>(Param)) {
      Position->push_back(i);
      if (ResolveTParamReferenceHelper(Name, TTP->getTemplateParameters(),
                                       Position))
        return true;
      Position->pop_back();
    }
  }
  return false;
}
} // end anonymous namespace

bool Sema::resolveTParamReference(
                            StringRef Name,
                            const TemplateParameterList *TemplateParameters,
                            SmallVectorImpl<unsigned> *Position) {
  Position->clear();
  if (!TemplateParameters)
    return false;

  return ResolveTParamReferenceHelper(Name, TemplateParameters, Position);
}

namespace {
void CorrectTypoInTParamReferenceHelper(
                            const TemplateParameterList *TemplateParameters,
                            SimpleTypoCorrector &Corrector) {
  for (unsigned i = 0, e = TemplateParameters->size(); i != e; ++i) {
    const NamedDecl *Param = TemplateParameters->getParam(i);
    Corrector.addDecl(Param);

    if (const TemplateTemplateParmDecl *TTP =
            dyn_cast<TemplateTemplateParmDecl>(Param))
      CorrectTypoInTParamReferenceHelper(TTP->getTemplateParameters(),
                                         Corrector);
  }
}
} // end anonymous namespace

StringRef Sema::correctTypoInTParamReference(
                            StringRef Typo,
                            const TemplateParameterList *TemplateParameters) {
  SimpleTypoCorrector Corrector(Typo);
  CorrectTypoInTParamReferenceHelper(TemplateParameters, Corrector);
  if (const NamedDecl *ND = Corrector.getBestDecl()) {
    const IdentifierInfo *II = ND->getIdentifier();
    assert(II && "SimpleTypoCorrector should not return this decl");
    return II->getName();
  }
  return StringRef();
}

InlineCommandComment::RenderKind
Sema::getInlineCommandRenderKind(StringRef Name) const {
  assert(Traits.getCommandInfo(Name)->IsInlineCommand);

  return llvm::StringSwitch<InlineCommandComment::RenderKind>(Name)
      .Case("b", InlineCommandComment::RenderBold)
      .Cases("c", "p", InlineCommandComment::RenderMonospaced)
      .Cases("a", "e", "em", InlineCommandComment::RenderEmphasized)
      .Case("anchor", InlineCommandComment::RenderAnchor)
      .Default(InlineCommandComment::RenderNormal);
}

} // end namespace comments
} // end namespace clang
