//===--- FunctionNamingCheck.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 "FunctionNamingCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "llvm/Support/Regex.h"

using namespace clang::ast_matchers;

namespace clang {
namespace tidy {
namespace google {
namespace objc {

namespace {

std::string validFunctionNameRegex(bool RequirePrefix) {
  // Allow the following name patterns for all functions:
  // • ABFoo (prefix + UpperCamelCase)
  // • ABURL (prefix + capitalized acronym/initialism)
  //
  // If no prefix is required, additionally allow the following name patterns:
  // • Foo (UpperCamelCase)
  // • URL (capitalized acronym/initialism)
  //
  // The function name following the prefix can contain standard and
  // non-standard capitalized character sequences including acronyms,
  // initialisms, and prefixes of symbols (e.g., UIColorFromNSString). For this
  // reason, the regex only verifies that the function name after the prefix
  // begins with a capital letter followed by an arbitrary sequence of
  // alphanumeric characters.
  //
  // If a prefix is required, the regex checks for a capital letter followed by
  // another capital letter or number that is part of the prefix and another
  // capital letter or number that begins the name following the prefix.
  std::string FunctionNameMatcher =
      std::string(RequirePrefix ? "[A-Z][A-Z0-9]+" : "") + "[A-Z][a-zA-Z0-9]*";
  return std::string("::(") + FunctionNameMatcher + ")$";
}

/// For now we will only fix functions of static storage class with names like
/// 'functionName' or 'function_name' and convert them to 'FunctionName'. For
/// other cases the user must determine an appropriate name on their own.
FixItHint generateFixItHint(const FunctionDecl *Decl) {
  // A fixit can be generated for functions of static storage class but
  // otherwise the check cannot determine the appropriate function name prefix
  // to use.
  if (Decl->getStorageClass() != SC_Static)
    return FixItHint();

  StringRef Name = Decl->getName();
  std::string NewName = Decl->getName().str();

  size_t Index = 0;
  bool AtWordBoundary = true;
  while (Index < NewName.size()) {
    char Ch = NewName[Index];
    if (isalnum(Ch)) {
      // Capitalize the first letter after every word boundary.
      if (AtWordBoundary) {
        NewName[Index] = toupper(NewName[Index]);
        AtWordBoundary = false;
      }

      // Advance the index after every alphanumeric character.
      Index++;
    } else {
      // Strip out any characters other than alphanumeric characters.
      NewName.erase(Index, 1);
      AtWordBoundary = true;
    }
  }

  // Generate a fixit hint if the new name is different.
  if (NewName != Name)
    return FixItHint::CreateReplacement(
        CharSourceRange::getTokenRange(SourceRange(Decl->getLocation())),
        llvm::StringRef(NewName));

  return FixItHint();
}

} // namespace

void FunctionNamingCheck::registerMatchers(MatchFinder *Finder) {
  // Enforce Objective-C function naming conventions on all functions except:
  // • Functions defined in system headers.
  // • C++ member functions.
  // • Namespaced functions.
  // • Implicitly defined functions.
  // • The main function.
  Finder->addMatcher(
      functionDecl(
          unless(anyOf(isExpansionInSystemHeader(), cxxMethodDecl(),
                       hasAncestor(namespaceDecl()), isMain(), isImplicit(),
                       matchesName(validFunctionNameRegex(true)),
                       allOf(isStaticStorageClass(),
                             matchesName(validFunctionNameRegex(false))))))
          .bind("function"),
      this);
}

void FunctionNamingCheck::check(const MatchFinder::MatchResult &Result) {
  const auto *MatchedDecl = Result.Nodes.getNodeAs<FunctionDecl>("function");

  bool IsGlobal = MatchedDecl->getStorageClass() != SC_Static;
  diag(MatchedDecl->getLocation(),
       "%select{static function|function in global namespace}1 named %0 must "
       "%select{be in|have an appropriate prefix followed by}1 Pascal case as "
       "required by Google Objective-C style guide")
      << MatchedDecl << IsGlobal << generateFixItHint(MatchedDecl);
}

} // namespace objc
} // namespace google
} // namespace tidy
} // namespace clang
