58 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "AssertEqualsCheck.h"10#include "llvm/ADT/StringMap.h"11 12#include <string>13 14using namespace clang::ast_matchers;15 16namespace clang::tidy::objc {17 18// Mapping from `XCTAssert*Equal` to `XCTAssert*EqualObjects` name.19static const llvm::StringMap<StringRef> NameMap{20 {"XCTAssertEqual", "XCTAssertEqualObjects"},21 {"XCTAssertNotEqual", "XCTAssertNotEqualObjects"},22};23 24void AssertEqualsCheck::registerMatchers(MatchFinder *Finder) {25 for (const auto &[CurrName, _] : NameMap) {26 Finder->addMatcher(27 binaryOperator(anyOf(hasOperatorName("!="), hasOperatorName("==")),28 isExpandedFromMacro(std::string(CurrName)),29 anyOf(hasLHS(hasType(qualType(30 hasCanonicalType(asString("NSString *"))))),31 hasRHS(hasType(qualType(32 hasCanonicalType(asString("NSString *")))))))33 .bind(CurrName),34 this);35 }36}37 38void AssertEqualsCheck::check(39 const ast_matchers::MatchFinder::MatchResult &Result) {40 for (const auto &[CurrName, TargetName] : NameMap) {41 if (const auto *Root = Result.Nodes.getNodeAs<BinaryOperator>(CurrName)) {42 const SourceManager *Sm = Result.SourceManager;43 // The macros are nested two levels, so going up twice.44 auto MacroCallsite = Sm->getImmediateMacroCallerLoc(45 Sm->getImmediateMacroCallerLoc(Root->getBeginLoc()));46 diag(MacroCallsite,47 (Twine("use ") + TargetName + " for comparing objects").str())48 << FixItHint::CreateReplacement(49 clang::CharSourceRange::getCharRange(50 MacroCallsite,51 MacroCallsite.getLocWithOffset(CurrName.size())),52 TargetName);53 }54 }55}56 57} // namespace clang::tidy::objc58