//===----------------------------------------------------------------------===//
//
// 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 "ConvertMemberFunctionsToStatic.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Lex/Lexer.h"

using namespace clang::ast_matchers;

namespace clang::tidy::readability {

namespace {

AST_MATCHER(CXXMethodDecl, isStatic) { return Node.isStatic(); }

AST_MATCHER(CXXMethodDecl, hasTrivialBody) { return Node.hasTrivialBody(); }

AST_MATCHER(CXXMethodDecl, isOverloadedOperator) {
  return Node.isOverloadedOperator();
}

AST_MATCHER(CXXRecordDecl, hasAnyDependentBases) {
  return Node.hasAnyDependentBases();
}

AST_MATCHER(CXXMethodDecl, isTemplate) {
  return Node.getTemplatedKind() != FunctionDecl::TK_NonTemplate;
}

AST_MATCHER(CXXMethodDecl, isDependentContext) {
  return Node.isDependentContext();
}

AST_MATCHER(CXXMethodDecl, isInsideMacroDefinition) {
  const ASTContext &Ctxt = Finder->getASTContext();
  return clang::Lexer::makeFileCharRange(
             clang::CharSourceRange::getCharRange(
                 Node.getTypeSourceInfo()->getTypeLoc().getSourceRange()),
             Ctxt.getSourceManager(), Ctxt.getLangOpts())
      .isInvalid();
}

AST_MATCHER_P(CXXMethodDecl, hasCanonicalDecl,
              ast_matchers::internal::Matcher<CXXMethodDecl>, InnerMatcher) {
  return InnerMatcher.matches(*Node.getCanonicalDecl(), Finder, Builder);
}

AST_MATCHER(CXXMethodDecl, usesThis) {
  class FindUsageOfThis : public RecursiveASTVisitor<FindUsageOfThis> {
  public:
    bool Used = false;

    bool VisitCXXThisExpr(const CXXThisExpr *E) {
      Used = true;
      return false; // Stop traversal.
    }

    // If we enter a class declaration, don't traverse into it as any usages of
    // `this` will correspond to the nested class.
    bool TraverseCXXRecordDecl(CXXRecordDecl *RD) { return true; }

  } UsageOfThis;

  // TraverseStmt does not modify its argument.
  UsageOfThis.TraverseStmt(Node.getBody());

  return UsageOfThis.Used;
}

} // namespace

void ConvertMemberFunctionsToStatic::registerMatchers(MatchFinder *Finder) {
  Finder->addMatcher(
      cxxMethodDecl(
          isDefinition(), isUserProvided(),
          unless(anyOf(
              isExpansionInSystemHeader(), isVirtual(), isStatic(),
              hasTrivialBody(), isOverloadedOperator(), cxxConstructorDecl(),
              cxxDestructorDecl(), cxxConversionDecl(),
              isExplicitObjectMemberFunction(), isTemplate(),
              isDependentContext(),
              ofClass(anyOf(
                  isLambda(),
                  hasAnyDependentBases()) // Method might become virtual
                                          // depending on template base class.
                      ),
              isInsideMacroDefinition(),
              hasCanonicalDecl(isInsideMacroDefinition()), usesThis())))
          .bind("x"),
      this);
}

/// Obtain the original source code text from a SourceRange.
static StringRef getStringFromRange(SourceManager &SourceMgr,
                                    const LangOptions &LangOpts,
                                    SourceRange Range) {
  if (SourceMgr.getFileID(Range.getBegin()) !=
      SourceMgr.getFileID(Range.getEnd()))
    return {};

  return Lexer::getSourceText(CharSourceRange(Range, true), SourceMgr,
                              LangOpts);
}

static SourceRange getLocationOfConst(const TypeSourceInfo *TSI,
                                      SourceManager &SourceMgr,
                                      const LangOptions &LangOpts) {
  assert(TSI);
  const auto FTL = TSI->getTypeLoc().IgnoreParens().getAs<FunctionTypeLoc>();
  assert(FTL);

  SourceRange Range{FTL.getRParenLoc().getLocWithOffset(1),
                    FTL.getLocalRangeEnd()};
  // Inside Range, there might be other keywords and trailing return types.
  // Find the exact position of "const".
  StringRef Text = getStringFromRange(SourceMgr, LangOpts, Range);
  size_t Offset = Text.find("const");
  if (Offset == StringRef::npos)
    return {};

  SourceLocation Start = Range.getBegin().getLocWithOffset(Offset);
  return {Start, Start.getLocWithOffset(strlen("const") - 1)};
}

void ConvertMemberFunctionsToStatic::check(
    const MatchFinder::MatchResult &Result) {
  const auto *Definition = Result.Nodes.getNodeAs<CXXMethodDecl>("x");

  // TODO: For out-of-line declarations, don't modify the source if the header
  // is excluded by the -header-filter option.
  DiagnosticBuilder Diag =
      diag(Definition->getLocation(), "method %0 can be made static")
      << Definition;

  // TODO: Would need to remove those in a fix-it.
  if (Definition->getMethodQualifiers().hasVolatile() ||
      Definition->getMethodQualifiers().hasRestrict() ||
      Definition->getRefQualifier() != RQ_None)
    return;

  const CXXMethodDecl *Declaration = Definition->getCanonicalDecl();

  if (Definition->isConst()) {
    // Make sure that we either remove 'const' on both declaration and
    // definition or emit no fix-it at all.
    SourceRange DefConst = getLocationOfConst(Definition->getTypeSourceInfo(),
                                              *Result.SourceManager,
                                              Result.Context->getLangOpts());

    if (DefConst.isInvalid())
      return;

    if (Declaration != Definition) {
      SourceRange DeclConst = getLocationOfConst(
          Declaration->getTypeSourceInfo(), *Result.SourceManager,
          Result.Context->getLangOpts());

      if (DeclConst.isInvalid())
        return;
      Diag << FixItHint::CreateRemoval(DeclConst);
    }

    // Remove existing 'const' from both declaration and definition.
    Diag << FixItHint::CreateRemoval(DefConst);
  }
  Diag << FixItHint::CreateInsertion(Declaration->getBeginLoc(), "static ");
}

} // namespace clang::tidy::readability
