//===--- AssertEquals.cpp - clang-tidy --------------------------*- C++ -*-===// // // 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 "AssertEquals.h" #include #include using namespace clang::ast_matchers; namespace clang::tidy::objc { // Mapping from `XCTAssert*Equal` to `XCTAssert*EqualObjects` name. static const std::map &NameMap() { static std::map map{ {"XCTAssertEqual", "XCTAssertEqualObjects"}, {"XCTAssertNotEqual", "XCTAssertNotEqualObjects"}, }; return map; } void AssertEquals::registerMatchers(MatchFinder *finder) { for (const auto &pair : NameMap()) { finder->addMatcher( binaryOperator(anyOf(hasOperatorName("!="), hasOperatorName("==")), isExpandedFromMacro(pair.first), anyOf(hasLHS(hasType(qualType( hasCanonicalType(asString("NSString *"))))), hasRHS(hasType(qualType( hasCanonicalType(asString("NSString *")))))) ) .bind(pair.first), this); } } void AssertEquals::check(const ast_matchers::MatchFinder::MatchResult &result) { for (const auto &pair : NameMap()) { if (const auto *root = result.Nodes.getNodeAs(pair.first)) { SourceManager *sm = result.SourceManager; // The macros are nested two levels, so going up twice. auto macro_callsite = sm->getImmediateMacroCallerLoc( sm->getImmediateMacroCallerLoc(root->getBeginLoc())); diag(macro_callsite, "use " + pair.second + " for comparing objects") << FixItHint::CreateReplacement( clang::CharSourceRange::getCharRange( macro_callsite, macro_callsite.getLocWithOffset(pair.first.length())), pair.second); } } } } // namespace clang::tidy::objc