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