dgatwood updated this revision to Diff 218953.
dgatwood marked 7 inline comments as done.
dgatwood added a comment.
Fixed a couple of variable names in the .h file, renamed
kCustomCategoryMethodIdentifier to CustomCategoryMethodIdentifier, and switched
to llvm::any_of.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D65917/new/
https://reviews.llvm.org/D65917
Files:
clang-tools-extra/clang-tidy/google/CMakeLists.txt
clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp
clang-tools-extra/clang-tidy/google/RequireCategoryMethodPrefixesCheck.cpp
clang-tools-extra/clang-tidy/google/RequireCategoryMethodPrefixesCheck.h
clang-tools-extra/docs/ReleaseNotes.rst
clang-tools-extra/docs/clang-tidy/checks/google-objc-require-category-method-prefixes.rst
clang-tools-extra/docs/clang-tidy/checks/list.rst
clang-tools-extra/test/clang-tidy/google-objc-require-category-method-prefixes.m
Index: clang-tools-extra/test/clang-tidy/google-objc-require-category-method-prefixes.m
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/google-objc-require-category-method-prefixes.m
@@ -0,0 +1,35 @@
+// RUN: %check_clang_tidy %s google-objc-require-category-method-prefixes %t -config="{CheckOptions: [{key: google-objc-require-category-method-prefixes.ExpectedPrefixes, value: GMO}]}"
+
+@class NSString;
+
+@interface NSURL
++ (nullable instancetype)URLWithString:(NSString *)URLString;
++ (instancetype)alloc;
+- (instancetype)init;
+@end
+
+@interface NSURL (CustomExtension)
+
+- (void)unprefixedMethod;
+- (void)unprefixed;
+- (void)justprefixed_;
+
+@end
+
+// CHECK-MESSAGES: :[[@LINE-6]]:1: warning: the category method 'unprefixedMethod' is not properly prefixed [google-objc-require-category-method-prefixes]
+// CHECK-MESSAGES: :[[@LINE-6]]:1: warning: the category method 'unprefixed' is not properly prefixed [google-objc-require-category-method-prefixes]
+// CHECK-MESSAGES: :[[@LINE-6]]:1: warning: the category method 'justprefixed_' is not properly prefixed [google-objc-require-category-method-prefixes]
+
+@interface NSURL (CustomExtension2)
+- (void)gmo_prefixedMethod;
+@end
+
+@interface GMOURL
++ (nullable instancetype)URLWithString:(NSString *)URLString;
++ (instancetype)alloc;
+- (instancetype)init;
+@end
+
+@interface GMOURL (CustomExtension3)
+- (void)unprefixedMethodInClassWithExpectedPrefix;
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===================================================================
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -230,6 +230,7 @@
google-objc-avoid-throwing-exception
google-objc-function-naming
google-objc-global-variable-declaration
+ google-objc-require-category-method-prefixes
google-readability-avoid-underscore-in-googletest-name
google-readability-braces-around-statements (redirects to readability-braces-around-statements) <google-readability-braces-around-statements>
google-readability-casting
Index: clang-tools-extra/docs/clang-tidy/checks/google-objc-require-category-method-prefixes.rst
===================================================================
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/google-objc-require-category-method-prefixes.rst
@@ -0,0 +1,44 @@
+.. title:: clang-tidy - google-objc-require-category-method-prefixes
+
+google-objc-require-category-method-prefixes
+============================================
+
+Warns when Objective-C category method names are not properly prefixed (e.g.
+``gmo_methodName``) unless the category is extending a class with an
+expected prefix (configurable).
+
+The Google Objective-C style guide requires
+`prefixes for methods http://go/objc-style#Category_Names`_ in categories on
+classes that you don't control (for example, categories on Apple or third-party
+framework classes or classes created by other teams) to prevent name collisions
+when those frameworks are updated.
+
+This checker ensures that all methods in categories have some sort of prefix
+(e.g. ``gmo_``). It excludes categories on classes whose names have a
+whitelisted three-letter prefix.
+
+For example, the following code sample is a properly prefixed method on a
+non-owned class (``NSObject``):
+
+.. code-block:: objc
+ @interface NSObject (QEDMyCategory)
+ - (BOOL)qed_myCustomMethod;
+ @end
+
+If you whitelist the ``QED`` three-letter prefix, the following code sample
+is also allowed:
+
+.. code-block:: objc
+
+ @interface QEDMyClass (MyCategory)
+ - (BOOL)myCustomMethod;
+ @end
+
+Options
+-------
+
+.. option:: ExpectedPrefixes
+
+ A semicolon-delimited list of class name prefixes. Methods in categories
+ that extend classes whose names begin with any of these prefixes are exempt
+ from the method name prefixing requirement.
Index: clang-tools-extra/docs/ReleaseNotes.rst
===================================================================
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -73,11 +73,12 @@
Finds instances where variables with static storage are initialized
dynamically in header files.
-- New :doc:`linuxkernel-must-use-errs
- <clang-tidy/checks/linuxkernel-must-use-errs>` check.
+- New :doc:`google-objc-require-category-method-prefixes
+ <clang-tidy/checks/google-objc-require-category-method-prefixes>` check.
- Checks Linux kernel code to see if it uses the results from the functions in
- ``linux/err.h``.
+ Warns when Objective-C category method names are not properly prefixed (e.g.
+ ``gmo_methodName``) unless the category is extending a class with a
+ (configurable) whitelisted prefix.
- New :doc:`google-upgrade-googletest-case
<clang-tidy/checks/google-upgrade-googletest-case>` check.
@@ -85,6 +86,12 @@
Finds uses of deprecated Googletest APIs with names containing ``case`` and
replaces them with equivalent APIs with ``suite``.
+- New :doc:`linuxkernel-must-use-errs
+ <clang-tidy/checks/linuxkernel-must-use-errs>` check.
+
+ Checks Linux kernel code to see if it uses the results from the functions in
+ ``linux/err.h``.
+
- New :doc:`llvm-prefer-register-over-unsigned
<clang-tidy/checks/llvm-prefer-register-over-unsigned>` check.
Index: clang-tools-extra/clang-tidy/google/RequireCategoryMethodPrefixesCheck.h
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/google/RequireCategoryMethodPrefixesCheck.h
@@ -0,0 +1,38 @@
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_REQUIRECATEGORYMETHODPREFIXES_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_REQUIRECATEGORYMETHODPREFIXES_H
+
+#include "../ClangTidyCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+namespace clang {
+namespace tidy {
+namespace google {
+namespace objc {
+
+// Warn about missing prefixes in category method names.
+class RequireCategoryMethodPrefixesCheck : public ClangTidyCheck {
+public:
+ RequireCategoryMethodPrefixesCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context),
+ ExpectedPrefixes(Options.get("ExpectedPrefixes", "")) {}
+
+ /// Make configuration of checker discoverable.
+ void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+ /// Semicolon-separated list of whitelisted class prefixes.
+ /// Defaults to empty.
+ const std::string ExpectedPrefixes;
+
+ bool matchesExpectedPrefix(StringRef ClassName);
+};
+
+} // namespace objc
+} // namespace google
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_REQUIRECATEGORYMETHODPREFIXES_H
Index: clang-tools-extra/clang-tidy/google/RequireCategoryMethodPrefixesCheck.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/google/RequireCategoryMethodPrefixesCheck.cpp
@@ -0,0 +1,97 @@
+#include "RequireCategoryMethodPrefixesCheck.h"
+
+#include "../ClangTidyOptions.h"
+#include "../utils/OptionsUtils.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+
+using namespace clang::ast_matchers; // NOLINT: Too many names.
+
+namespace clang {
+namespace tidy {
+namespace google {
+namespace objc {
+
+static const char *CustomCategoryMethodIdentifier = "ThisIsACategoryMethod";
+
+void RequireCategoryMethodPrefixesCheck::registerMatchers(MatchFinder *Finder) {
+ // This check should be run only on Objective-C code.
+ if (!getLangOpts().ObjC)
+ return;
+
+ Finder->addMatcher(objcMethodDecl().bind(CustomCategoryMethodIdentifier),
+ this);
+}
+
+void RequireCategoryMethodPrefixesCheck::storeOptions(
+ ClangTidyOptions::OptionMap &Opts) {
+ Options.store(Opts, "ExpectedPrefixes", ExpectedPrefixes);
+}
+
+bool RequireCategoryMethodPrefixesCheck::matchesExpectedPrefix(
+ StringRef ClassName) {
+ std::vector<std::string> PrefixArray =
+ utils::options::parseStringList(ExpectedPrefixes);
+
+ return llvm::any_of(PrefixArray,
+ [ClassName](const std::string &Str) {
+ return ClassName.startswith(Str);
+ });
+}
+
+void RequireCategoryMethodPrefixesCheck::check(
+ const MatchFinder::MatchResult &Result) {
+ const ObjCMethodDecl *MethodDeclaration =
+ Result.Nodes.getNodeAs<ObjCMethodDecl>(CustomCategoryMethodIdentifier);
+ if (!MethodDeclaration)
+ return;
+
+ // We cannot safely use getName here, because it will often fail with
+ // the error "Name is not a simple identifier", and getIdentifier() returns
+ // nullptr.
+ StringRef MethodName = MethodDeclaration->getNameAsString();
+ const ObjCInterfaceDecl *OwningObjCClassInterface =
+ MethodDeclaration->getClassInterface();
+ if (!OwningObjCClassInterface)
+ return;
+
+ StringRef ClassName = OwningObjCClassInterface->getName();
+
+ const auto *OwningObjCCategory =
+ dyn_cast<ObjCCategoryDecl>(MethodDeclaration->getDeclContext());
+ // Bail early if the method is not in a category.
+ if (!OwningObjCCategory || OwningObjCCategory->isInvalidDecl())
+ return;
+
+ // Bail early if the method is in a category on a class with a whitelisted
+ // prefix.
+ if (matchesExpectedPrefix(ClassName))
+ return;
+
+ // Check whether the method name has a proper prefix.
+ for (const char *pos = MethodName.str().c_str(); pos && *pos; ++pos) {
+ // The characters a-z are allowed in a prefix. Go to the next
+ // character.
+ if (*pos >= 'a' && *pos <= 'z')
+ continue;
+
+ // The underscore character (_) terminates the prefix. As long as it is
+ // not the last character in the name, the declaration passes.
+ if (*pos == '_' && *(pos + 1) != '\0')
+ return;
+
+ // The name does not start with /[a-z]+_/. This declaration fails.
+ break;
+ }
+ // If the end of the string is reached or an illegal character appears
+ // before the terminating underscore, then the method name is not
+ // properly prefixed. Throw an error.
+ diag(MethodDeclaration->getBeginLoc(),
+ "the category method %0 is not properly prefixed")
+ << MethodDeclaration;
+}
+
+} // namespace objc
+} // namespace google
+} // namespace tidy
+} // namespace clang
Index: clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp
===================================================================
--- clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp
+++ clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp
@@ -25,6 +25,7 @@
#include "IntegerTypesCheck.h"
#include "NonConstReferences.h"
#include "OverloadedUnaryAndCheck.h"
+#include "RequireCategoryMethodPrefixesCheck.h"
#include "TodoCommentCheck.h"
#include "UnnamedNamespaceInHeaderCheck.h"
#include "UpgradeGoogletestCaseCheck.h"
@@ -59,6 +60,8 @@
"google-objc-function-naming");
CheckFactories.registerCheck<objc::GlobalVariableDeclarationCheck>(
"google-objc-global-variable-declaration");
+ CheckFactories.registerCheck<objc::RequireCategoryMethodPrefixesCheck>(
+ "google-objc-require-category-method-prefixes");
CheckFactories.registerCheck<runtime::IntegerTypesCheck>(
"google-runtime-int");
CheckFactories.registerCheck<runtime::OverloadedUnaryAndCheck>(
Index: clang-tools-extra/clang-tidy/google/CMakeLists.txt
===================================================================
--- clang-tools-extra/clang-tidy/google/CMakeLists.txt
+++ clang-tools-extra/clang-tidy/google/CMakeLists.txt
@@ -15,6 +15,7 @@
IntegerTypesCheck.cpp
NonConstReferences.cpp
OverloadedUnaryAndCheck.cpp
+ RequireCategoryMethodPrefixesCheck.cpp
TodoCommentCheck.cpp
UnnamedNamespaceInHeaderCheck.cpp
UpgradeGoogletestCaseCheck.cpp
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits