//===--- ConstReturnTypeCheck.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 "ConstReturnTypeCheck.h"
#include "../utils/LexerUtils.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/Optional.h"

using namespace clang::ast_matchers;

namespace clang {
namespace tidy {
namespace readability {

// Finds the location of the qualifying `const` token in the `FunctionDecl`'s
// return type. Returns `None` when the return type is not `const`-qualified or
// `const` does not appear in `Def`'s source, like when the type is an alias or
// a macro.
static llvm::Optional<Token>
findConstToRemove(const FunctionDecl *Def,
                  const MatchFinder::MatchResult &Result) {
  if (!Def->getReturnType().isLocalConstQualified())
    return None;

  // Get the begin location for the function name, including any qualifiers
  // written in the source (for out-of-line declarations). A FunctionDecl's
  // "location" is the start of its name, so, when the name is unqualified, we
  // use `getLocation()`.
  SourceLocation NameBeginLoc = Def->getQualifier()
                                    ? Def->getQualifierLoc().getBeginLoc()
                                    : Def->getLocation();
  // Since either of the locs can be in a macro, use `makeFileCharRange` to be
  // sure that we have a consistent `CharSourceRange`, located entirely in the
  // source file.
  CharSourceRange FileRange = Lexer::makeFileCharRange(
      CharSourceRange::getCharRange(Def->getBeginLoc(), NameBeginLoc),
      *Result.SourceManager, Result.Context->getLangOpts());

  if (FileRange.isInvalid())
    return None;

  return utils::lexer::getConstQualifyingToken(FileRange, *Result.Context,
                                               *Result.SourceManager);
}

namespace {

struct CheckResult {
  // Source range of the relevant `const` token in the definition being checked.
  CharSourceRange ConstRange;

  // FixItHints associated with the definition being checked.
  llvm::SmallVector<clang::FixItHint, 4> Hints;

  // Locations of any declarations that could not be fixed.
  llvm::SmallVector<clang::SourceLocation, 4> DeclLocs;
};

} // namespace

// Does the actual work of the check.
static CheckResult checkDef(const clang::FunctionDecl *Def,
                            const MatchFinder::MatchResult &MatchResult) {
  CheckResult Result;
  llvm::Optional<Token> Tok = findConstToRemove(Def, MatchResult);
  if (!Tok)
    return Result;

  Result.ConstRange =
      CharSourceRange::getCharRange(Tok->getLocation(), Tok->getEndLoc());
  Result.Hints.push_back(FixItHint::CreateRemoval(Result.ConstRange));

  // Fix the definition and any visible declarations, but don't warn
  // seperately for each declaration. Instead, associate all fixes with the
  // single warning at the definition.
  for (const FunctionDecl *Decl = Def->getPreviousDecl(); Decl != nullptr;
       Decl = Decl->getPreviousDecl()) {
    if (llvm::Optional<Token> T = findConstToRemove(Decl, MatchResult))
      Result.Hints.push_back(FixItHint::CreateRemoval(
          CharSourceRange::getCharRange(T->getLocation(), T->getEndLoc())));
    else
      // `getInnerLocStart` gives the start of the return type.
      Result.DeclLocs.push_back(Decl->getInnerLocStart());
  }
  return Result;
}

void ConstReturnTypeCheck::registerMatchers(MatchFinder *Finder) {
  // Find all function definitions for which the return types are `const`
  // qualified.
  Finder->addMatcher(
      functionDecl(returns(isConstQualified()), isDefinition()).bind("func"),
      this);
}

void ConstReturnTypeCheck::check(const MatchFinder::MatchResult &Result) {
  const auto *Def = Result.Nodes.getNodeAs<FunctionDecl>("func");
  CheckResult CR = checkDef(Def, Result);
  {
    // Clang only supports one in-flight diagnostic at a time. So, delimit the
    // scope of `Diagnostic` to allow further diagnostics after the scope.  We
    // use `getInnerLocStart` to get the start of the return type.
    DiagnosticBuilder Diagnostic =
        diag(Def->getInnerLocStart(),
             "return type %0 is 'const'-qualified at the top level, which may "
             "reduce code readability without improving const correctness")
        << Def->getReturnType();
    if (CR.ConstRange.isValid())
      Diagnostic << CR.ConstRange;
    for (auto &Hint : CR.Hints)
      Diagnostic << Hint;
  }
  for (auto Loc : CR.DeclLocs)
    diag(Loc, "could not transform this declaration", DiagnosticIDs::Note);
}

} // namespace readability
} // namespace tidy
} // namespace clang
