Index: clang-tidy/objc/CMakeLists.txt =================================================================== --- clang-tidy/objc/CMakeLists.txt +++ clang-tidy/objc/CMakeLists.txt @@ -4,6 +4,7 @@ AvoidNSErrorInitCheck.cpp AvoidSpinlockCheck.cpp ForbiddenSubclassingCheck.cpp + IvarDeclarationCheck.cpp ObjCTidyModule.cpp PropertyDeclarationCheck.cpp Index: clang-tidy/objc/IvarDeclarationCheck.h =================================================================== --- /dev/null +++ clang-tidy/objc/IvarDeclarationCheck.h @@ -0,0 +1,35 @@ +//===--- IvarDeclarationCheck.h - clang-tidy---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBJC_IVARDECLARATIONCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBJC_IVARDECLARATIONCHECK_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace objc { + +/// Finds Objective-C ivars which do not have '_' prefix. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/objc-ivar-declaration.html +class IvarDeclarationCheck : public ClangTidyCheck { +public: + IvarDeclarationCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace objc +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBJC_IVARDECLARATIONCHECK_H Index: clang-tidy/objc/IvarDeclarationCheck.cpp =================================================================== --- /dev/null +++ clang-tidy/objc/IvarDeclarationCheck.cpp @@ -0,0 +1,52 @@ +//===--- IvarDeclarationCheck.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 "IvarDeclarationCheck.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 objc { + +namespace { + +FixItHint generateFixItHint(const ObjCIvarDecl *Decl) { + auto IvarName = Decl->getName(); + if (IvarName[0] != '_') { + auto NewName = Decl->getName().str(); + NewName.insert(0, 1, '_'); + return FixItHint::CreateReplacement( + CharSourceRange::getTokenRange(SourceRange(Decl->getLocation())), + llvm::StringRef(NewName)); + } + return FixItHint(); +} +} // namespace + +void IvarDeclarationCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher( + objcIvarDecl(unless(matchesName("::_[a-zA-Z]+[a-zA-Z0-9_]*"))) + .bind("ivar"), + this); +} + +void IvarDeclarationCheck::check(const MatchFinder::MatchResult &Result) { + const auto *MatchedDecl = Result.Nodes.getNodeAs("ivar"); + diag(MatchedDecl->getLocation(), + "instance variable %0 not using '_' as prefix") + << MatchedDecl << generateFixItHint(MatchedDecl); +} + +} // namespace objc +} // namespace tidy +} // namespace clang Index: clang-tidy/objc/ObjCTidyModule.cpp =================================================================== --- clang-tidy/objc/ObjCTidyModule.cpp +++ clang-tidy/objc/ObjCTidyModule.cpp @@ -13,6 +13,7 @@ #include "AvoidNSErrorInitCheck.h" #include "AvoidSpinlockCheck.h" #include "ForbiddenSubclassingCheck.h" +#include "IvarDeclarationCheck.h" #include "PropertyDeclarationCheck.h" using namespace clang::ast_matchers; @@ -30,6 +31,8 @@ "objc-avoid-spinlock"); CheckFactories.registerCheck( "objc-forbidden-subclassing"); + CheckFactories.registerCheck( + "objc-ivar-declaration"); CheckFactories.registerCheck( "objc-property-declaration"); } Index: docs/ReleaseNotes.rst =================================================================== --- docs/ReleaseNotes.rst +++ docs/ReleaseNotes.rst @@ -57,6 +57,11 @@ Improvements to clang-tidy -------------------------- +- New :doc:`objc-ivar-declaration + ` check + + New check that finds Objective-C ivars that do not have a '_' prefix. + - New module `abseil` for checks related to the `Abseil `_ library. Index: docs/clang-tidy/checks/list.rst =================================================================== --- docs/clang-tidy/checks/list.rst +++ docs/clang-tidy/checks/list.rst @@ -187,6 +187,7 @@ objc-avoid-nserror-init objc-avoid-spinlock objc-forbidden-subclassing + objc-ivar-declaration objc-property-declaration performance-faster-string-find performance-for-range-copy Index: docs/clang-tidy/checks/objc-ivar-declaration.rst =================================================================== --- /dev/null +++ docs/clang-tidy/checks/objc-ivar-declaration.rst @@ -0,0 +1,21 @@ +.. title:: clang-tidy - objc-ivar-declaration + +objc-ivar-declaration +===================== + +Finds ivar declarations in Objective-C files that do not follow the pattern +in Apple's programming guide. The ivar name should be fixed with '_'. + +For code of ivar declaration: + +.. code-block:: objc + + int barWithoutPrefix; + +The fix will be: + +.. code-block:: objc + + int _barWithoutPrefix; + +The corresponding style rule: https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingIvarsAndTypes.html#//apple_ref/doc/uid/20001284-1001757 \ No newline at end of file Index: test/clang-tidy/objc-ivar-declaration.m =================================================================== --- /dev/null +++ test/clang-tidy/objc-ivar-declaration.m @@ -0,0 +1,11 @@ +// RUN: %check_clang_tidy %s objc-ivar-declaration %t +@interface Foo +@end + +@interface Foo () { + int _bar; + int barWithoutPrefix; + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: instance variable 'barWithoutPrefix' not using '_' as prefix [objc-ivar-declaration] + // CHECK-FIXES: int _barWithoutPrefix; +} +@end