//===- AbseilMatcher.h - clang-tidy ---------------------------------------===// // // 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 "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include namespace clang::ast_matchers { /// Matches AST nodes that were found within Abseil files. /// /// Example matches Y but not X /// (matcher = cxxRecordDecl(isInAbseilFile()) /// \code /// #include "absl/strings/internal-file.h" /// class X {}; /// \endcode /// absl/strings/internal-file.h: /// \code /// class Y {}; /// \endcode /// /// Usable as: Matcher, Matcher, Matcher, /// Matcher AST_POLYMORPHIC_MATCHER( isInAbseilFile, AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Stmt, TypeLoc, NestedNameSpecifierLoc)) { auto &SourceManager = Finder->getASTContext().getSourceManager(); SourceLocation Loc = SourceManager.getSpellingLoc(Node.getBeginLoc()); if (Loc.isInvalid()) return false; OptionalFileEntryRef FileEntry = SourceManager.getFileEntryRefForID(SourceManager.getFileID(Loc)); if (!FileEntry) return false; // Determine whether filepath contains "absl/[absl-library]" substring, where // [absl-library] is AbseilLibraries list entry. StringRef Path = FileEntry->getName(); static constexpr llvm::StringLiteral AbslPrefix("absl/"); size_t PrefixPosition = Path.find(AbslPrefix); if (PrefixPosition == StringRef::npos) return false; Path = Path.drop_front(PrefixPosition + AbslPrefix.size()); static const char *AbseilLibraries[] = { "algorithm", "base", "container", "debugging", "flags", "hash", "iterator", "memory", "meta", "numeric", "profiling", "random", "status", "strings", "synchronization", "time", "types", "utility"}; return llvm::any_of(AbseilLibraries, [&](const char *Library) { return Path.starts_with(Library); }); } } // namespace clang::ast_matchers