1 | //===- AbseilMatcher.h - clang-tidy ---------------------------------------===// |
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-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "clang/AST/ASTContext.h" |
10 | #include "clang/ASTMatchers/ASTMatchFinder.h" |
11 | #include <algorithm> |
12 | |
13 | namespace clang::ast_matchers { |
14 | |
15 | /// Matches AST nodes that were found within Abseil files. |
16 | /// |
17 | /// Example matches Y but not X |
18 | /// (matcher = cxxRecordDecl(isInAbseilFile()) |
19 | /// \code |
20 | /// #include "absl/strings/internal-file.h" |
21 | /// class X {}; |
22 | /// \endcode |
23 | /// absl/strings/internal-file.h: |
24 | /// \code |
25 | /// class Y {}; |
26 | /// \endcode |
27 | /// |
28 | /// Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc>, |
29 | /// Matcher<NestedNameSpecifierLoc> |
30 | AST_POLYMORPHIC_MATCHER( |
31 | isInAbseilFile, AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Stmt, TypeLoc, |
32 | NestedNameSpecifierLoc)) { |
33 | auto &SourceManager = Finder->getASTContext().getSourceManager(); |
34 | SourceLocation Loc = SourceManager.getSpellingLoc(Loc: Node.getBeginLoc()); |
35 | if (Loc.isInvalid()) |
36 | return false; |
37 | OptionalFileEntryRef FileEntry = |
38 | SourceManager.getFileEntryRefForID(FID: SourceManager.getFileID(SpellingLoc: Loc)); |
39 | if (!FileEntry) |
40 | return false; |
41 | // Determine whether filepath contains "absl/[absl-library]" substring, where |
42 | // [absl-library] is AbseilLibraries list entry. |
43 | StringRef Path = FileEntry->getName(); |
44 | static constexpr llvm::StringLiteral AbslPrefix("absl/" ); |
45 | size_t PrefixPosition = Path.find(Str: AbslPrefix); |
46 | if (PrefixPosition == StringRef::npos) |
47 | return false; |
48 | Path = Path.drop_front(N: PrefixPosition + AbslPrefix.size()); |
49 | static const char *AbseilLibraries[] = { |
50 | "algorithm" , "base" , "container" , "debugging" , "flags" , |
51 | "hash" , "iterator" , "memory" , "meta" , "numeric" , |
52 | "profiling" , "random" , "status" , "strings" , "synchronization" , |
53 | "time" , "types" , "utility" }; |
54 | return llvm::any_of(AbseilLibraries, [&](const char *Library) { |
55 | return Path.starts_with(Prefix: Library); |
56 | }); |
57 | } |
58 | |
59 | } // namespace clang::ast_matchers |
60 | |