|  | //===--- 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 <map> | 
|  | #include <string> | 
|  |  | 
|  | using namespace clang::ast_matchers; | 
|  |  | 
|  | namespace clang::tidy::objc { | 
|  |  | 
|  | // Mapping from `XCTAssert*Equal` to `XCTAssert*EqualObjects` name. | 
|  | static const std::map<std::string, std::string> &NameMap() { | 
|  | static std::map<std::string, std::string> 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<BinaryOperator>(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 |