//===--- PropertyDeclarationCheck.cpp - clang-tidy-------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "PropertyDeclarationCheck.h"
#include <algorithm>
#include "../utils/OptionsUtils.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Basic/CharInfo.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Regex.h"

using namespace clang::ast_matchers;

namespace clang {
namespace tidy {
namespace objc {

namespace {

// For StandardProperty the naming style is 'lowerCamelCase'.
// For CategoryProperty especially in categories of system class,
// to avoid naming conflict, the suggested naming style is
// 'abc_lowerCamelCase' (adding lowercase prefix followed by '_').
enum NamingStyle {
  StandardProperty = 1,
  CategoryProperty = 2,
};

/// The acronyms are aggregated from multiple sources including
/// https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/APIAbbreviations.html#//apple_ref/doc/uid/20001285-BCIHCGAE
///
/// Keep this list sorted.
constexpr llvm::StringLiteral DefaultSpecialAcronyms[] = {
    "[2-9]G",
    "ACL",
    "API",
    "AR",
    "ARGB",
    "ASCII",
    "AV",
    "BGRA",
    "CA",
    "CF",
    "CG",
    "CI",
    "CRC",
    "CV",
    "CMYK",
    "DNS",
    "FPS",
    "FTP",
    "GIF",
    "GL",
    "GPS",
    "GUID",
    "HD",
    "HDR",
    "HMAC",
    "HTML",
    "HTTP",
    "HTTPS",
    "HUD",
    "ID",
    "JPG",
    "JS",
    "LAN",
    "LZW",
    "MAC",
    "MD",
    "MDNS",
    "MIDI",
    "NS",
    "OS",
    "PDF",
    "PIN",
    "PNG",
    "POI",
    "PSTN",
    "PTR",
    "QA",
    "QOS",
    "RGB",
    "RGBA",
    "RGBX",
    "RIPEMD",
    "ROM",
    "RPC",
    "RTF",
    "RTL",
    "SC",
    "SDK",
    "SHA",
    "SQL",
    "SSO",
    "TCP",
    "TIFF",
    "TTS",
    "UI",
    "URI",
    "URL",
    "UUID",
    "VC",
    "VOIP",
    "VPN",
    "VR",
    "W",
    "WAN",
    "X",
    "XML",
    "Y",
    "Z",
};

/// For now we will only fix 'CamelCase' or 'abc_CamelCase' property to
/// 'camelCase' or 'abc_camelCase'. For other cases the users need to
/// come up with a proper name by their own.
/// FIXME: provide fix for snake_case to snakeCase
FixItHint generateFixItHint(const ObjCPropertyDecl *Decl, NamingStyle Style) {
  auto Name = Decl->getName();
  auto NewName = Decl->getName().str();
  size_t Index = 0;
  if (Style == CategoryProperty) {
    Index = Name.find_first_of('_') + 1;
    NewName.replace(0, Index - 1, Name.substr(0, Index - 1).lower());
  }
  if (Index < Name.size()) {
    NewName[Index] = tolower(NewName[Index]);
    if (NewName != Name) {
      return FixItHint::CreateReplacement(
          CharSourceRange::getTokenRange(SourceRange(Decl->getLocation())),
          llvm::StringRef(NewName));
    }
  }
  return FixItHint();
}

std::string AcronymsGroupRegex(llvm::ArrayRef<std::string> EscapedAcronyms) {
  return "(" +
         llvm::join(EscapedAcronyms.begin(), EscapedAcronyms.end(), "s?|") +
         "s?)";
}

std::string validPropertyNameRegex(llvm::ArrayRef<std::string> EscapedAcronyms,
                                   bool UsedInMatcher) {
  // Allow any of these names:
  // foo
  // fooBar
  // url
  // urlString
  // URL
  // URLString
  // bundleID
  std::string StartMatcher = UsedInMatcher ? "::" : "^";
  std::string AcronymsMatcher = AcronymsGroupRegex(EscapedAcronyms);
  return StartMatcher + "(" + AcronymsMatcher + "[A-Z]?)?[a-z]+[a-z0-9]*(" +
         AcronymsMatcher + "|([A-Z][a-z0-9]+)|A|I)*$";
}

bool hasCategoryPropertyPrefix(llvm::StringRef PropertyName) {
  auto RegexExp = llvm::Regex("^[a-zA-Z]+_[a-zA-Z0-9][a-zA-Z0-9_]+$");
  return RegexExp.match(PropertyName);
}

bool prefixedPropertyNameValid(llvm::StringRef PropertyName,
                               llvm::ArrayRef<std::string> Acronyms) {
  size_t Start = PropertyName.find_first_of('_');
  assert(Start != llvm::StringRef::npos && Start + 1 < PropertyName.size());
  auto Prefix = PropertyName.substr(0, Start);
  if (Prefix.lower() != Prefix) {
    return false;
  }
  auto RegexExp =
      llvm::Regex(llvm::StringRef(validPropertyNameRegex(Acronyms, false)));
  return RegexExp.match(PropertyName.substr(Start + 1));
}
}  // namespace

PropertyDeclarationCheck::PropertyDeclarationCheck(StringRef Name,
                                                   ClangTidyContext *Context)
    : ClangTidyCheck(Name, Context),
      SpecialAcronyms(
          utils::options::parseStringList(Options.get("Acronyms", ""))),
      IncludeDefaultAcronyms(Options.get("IncludeDefaultAcronyms", true)),
      EscapedAcronyms() {}

void PropertyDeclarationCheck::registerMatchers(MatchFinder *Finder) {
  // this check should only be applied to ObjC sources.
  if (!getLangOpts().ObjC1 && !getLangOpts().ObjC2) {
    return;
  }
  if (IncludeDefaultAcronyms) {
    EscapedAcronyms.reserve(llvm::array_lengthof(DefaultSpecialAcronyms) +
                            SpecialAcronyms.size());
    // No need to regex-escape the default acronyms.
    EscapedAcronyms.insert(EscapedAcronyms.end(),
                           std::begin(DefaultSpecialAcronyms),
                           std::end(DefaultSpecialAcronyms));
  } else {
    EscapedAcronyms.reserve(SpecialAcronyms.size());
  }
  // In case someone defines a prefix which includes a regex
  // special character, regex-escape all the user-defined prefixes.
  std::transform(SpecialAcronyms.begin(), SpecialAcronyms.end(),
                 std::back_inserter(EscapedAcronyms),
                 [](const std::string &s) { return llvm::Regex::escape(s); });
  Finder->addMatcher(
      objcPropertyDecl(
          // the property name should be in Lower Camel Case like
          // 'lowerCamelCase'
          unless(matchesName(validPropertyNameRegex(EscapedAcronyms, true))))
          .bind("property"),
      this);
}

void PropertyDeclarationCheck::check(const MatchFinder::MatchResult &Result) {
  const auto *MatchedDecl =
      Result.Nodes.getNodeAs<ObjCPropertyDecl>("property");
  assert(MatchedDecl->getName().size() > 0);
  auto *DeclContext = MatchedDecl->getDeclContext();
  auto *CategoryDecl = llvm::dyn_cast<ObjCCategoryDecl>(DeclContext);

  auto AcronymsRegex =
      llvm::Regex("^" + AcronymsGroupRegex(EscapedAcronyms) + "$");
  if (AcronymsRegex.match(MatchedDecl->getName())) {
    return;
  }
  if (CategoryDecl != nullptr &&
      hasCategoryPropertyPrefix(MatchedDecl->getName())) {
    if (!prefixedPropertyNameValid(MatchedDecl->getName(), EscapedAcronyms) ||
        CategoryDecl->IsClassExtension()) {
      NamingStyle Style = CategoryDecl->IsClassExtension() ? StandardProperty
                                                           : CategoryProperty;
      diag(MatchedDecl->getLocation(),
           "property name '%0' not using lowerCamelCase style or not prefixed "
           "in a category, according to the Apple Coding Guidelines")
          << MatchedDecl->getName() << generateFixItHint(MatchedDecl, Style);
    }
    return;
  }
  diag(MatchedDecl->getLocation(),
       "property name '%0' not using lowerCamelCase style or not prefixed in "
       "a category, according to the Apple Coding Guidelines")
      << MatchedDecl->getName()
      << generateFixItHint(MatchedDecl, StandardProperty);
}

void PropertyDeclarationCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
  Options.store(Opts, "Acronyms",
                utils::options::serializeStringList(SpecialAcronyms));
  Options.store(Opts, "IncludeDefaultAcronyms", IncludeDefaultAcronyms);
}

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