File: PropertyDeclarationCheck.cpp

package info (click to toggle)
llvm-toolchain-6.0 1%3A6.0.1-10
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 598,080 kB
  • sloc: cpp: 3,046,253; ansic: 595,057; asm: 271,965; python: 128,926; objc: 106,554; sh: 21,906; lisp: 10,191; pascal: 6,094; ml: 5,544; perl: 5,265; makefile: 2,227; cs: 2,027; xml: 686; php: 212; csh: 117
file content (115 lines) | stat: -rw-r--r-- 3,729 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
//===--- 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 "../utils/OptionsUtils.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Regex.h"
#include <algorithm>

using namespace clang::ast_matchers;

namespace clang {
namespace tidy {
namespace objc {

namespace {
/// The acronyms are from
/// https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/APIAbbreviations.html#//apple_ref/doc/uid/20001285-BCIHCGAE
constexpr char DefaultSpecialAcronyms[] =
    "ASCII;"
    "PDF;"
    "XML;"
    "HTML;"
    "URL;"
    "RTF;"
    "HTTP;"
    "TIFF;"
    "JPG;"
    "PNG;"
    "GIF;"
    "LZW;"
    "ROM;"
    "RGB;"
    "CMYK;"
    "MIDI;"
    "FTP";

/// For now we will only fix 'CamelCase' property to
/// '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) {
  if (isupper(Decl->getName()[0])) {
    auto NewName = Decl->getName().str();
    NewName[0] = tolower(NewName[0]);
    return FixItHint::CreateReplacement(
        CharSourceRange::getTokenRange(SourceRange(Decl->getLocation())),
        llvm::StringRef(NewName));
  }
  return FixItHint();
}

std::string validPropertyNameRegex(const std::vector<std::string> &Prefixes) {
  std::vector<std::string> EscapedPrefixes;
  EscapedPrefixes.reserve(Prefixes.size());
  // In case someone defines a custom prefix which includes a regex
  // special character, escape all the prefixes.
  std::transform(Prefixes.begin(), Prefixes.end(),
                 std::back_inserter(EscapedPrefixes), [](const std::string& s) {
                   return llvm::Regex::escape(s); });
  // Allow any of these names:
  // foo
  // fooBar
  // url
  // urlString
  // URL
  // URLString
  return std::string("::((") +
      llvm::join(EscapedPrefixes.begin(), EscapedPrefixes.end(), "|") +
      ")[A-Z]?)?[a-z]+[a-z0-9]*([A-Z][a-z0-9]+)*$";
}
}  // namespace

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

void PropertyDeclarationCheck::registerMatchers(MatchFinder *Finder) {
  Finder->addMatcher(
      objcPropertyDecl(
          // the property name should be in Lower Camel Case like
          // 'lowerCamelCase'
          unless(matchesName(validPropertyNameRegex(SpecialAcronyms))))
          .bind("property"),
      this);
}

void PropertyDeclarationCheck::check(const MatchFinder::MatchResult &Result) {
  const auto *MatchedDecl =
      Result.Nodes.getNodeAs<ObjCPropertyDecl>("property");
  assert(MatchedDecl->getName().size() > 0);
  diag(MatchedDecl->getLocation(),
       "property name '%0' should use lowerCamelCase style, according to "
       "the Apple Coding Guidelines")
      << MatchedDecl->getName() << generateFixItHint(MatchedDecl);
}

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

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