16 #include "clang/AST/AST.h"
17 #include "clang/AST/ASTContext.h"
18 #include "clang/AST/RecursiveASTVisitor.h"
19 #include "clang/Index/USRGeneration.h"
20 #include "clang/Lex/Lexer.h"
21 #include "llvm/ADT/SmallVector.h"
32 class NamedDeclFindingASTVisitor
33 :
public clang::RecursiveASTVisitor<NamedDeclFindingASTVisitor> {
37 explicit NamedDeclFindingASTVisitor(
const SourceManager &
SourceMgr,
38 const SourceLocation
Point)
39 :
Result(nullptr), SourceMgr(SourceMgr),
45 explicit NamedDeclFindingASTVisitor(
const SourceManager &
SourceMgr,
46 const std::string &
Name)
47 :
Result(nullptr), SourceMgr(SourceMgr),
57 bool VisitNamedDecl(
const NamedDecl *Decl) {
58 return setResult(Decl, Decl->getLocation(),
59 Decl->getNameAsString().length());
64 bool VisitDeclRefExpr(
const DeclRefExpr *Expr) {
66 if (!checkNestedNameSpecifierLoc(Expr->getQualifierLoc()))
69 const auto *Decl = Expr->getFoundDecl();
70 return setResult(Decl, Expr->getLocation(),
71 Decl->getNameAsString().length());
74 bool VisitMemberExpr(
const MemberExpr *Expr) {
75 const auto *Decl = Expr->getFoundDecl().getDecl();
76 return setResult(Decl, Expr->getMemberLoc(),
77 Decl->getNameAsString().length());
82 const NamedDecl *getNamedDecl() {
89 bool checkNestedNameSpecifierLoc(NestedNameSpecifierLoc NameLoc) {
91 const auto *Decl = NameLoc.getNestedNameSpecifier()->getAsNamespace();
92 if (Decl && !setResult(Decl, NameLoc.getLocalBeginLoc(),
93 Decl->getNameAsString().length()))
95 NameLoc = NameLoc.getPrefix();
102 bool setResult(
const NamedDecl *Decl, SourceLocation Start,
103 SourceLocation End) {
106 if (!Start.isValid() || !Start.isFileID() || !End.isValid() ||
107 !End.isFileID() || !isPointWithin(Start, End)) {
112 if (
Name != Decl->getQualifiedNameAsString()) {
122 bool setResult(
const NamedDecl *Decl, SourceLocation
Loc,
125 return Offset == 0 ||
126 setResult(Decl, Loc, Loc.getLocWithOffset(Offset - 1));
130 bool isPointWithin(
const SourceLocation Start,
const SourceLocation End) {
145 const SourceLocation
Point) {
146 const auto &
SourceMgr = Context.getSourceManager();
147 const auto SearchFile =
SourceMgr.getFilename(Point);
149 NamedDeclFindingASTVisitor Visitor(
SourceMgr, Point);
152 auto Decls = Context.getTranslationUnitDecl()->decls();
153 for (
auto &CurrDecl : Decls) {
154 const auto FileLoc = CurrDecl->getLocStart();
155 const auto FileName =
SourceMgr.getFilename(FileLoc);
157 if (FileName == SearchFile) {
158 Visitor.TraverseDecl(CurrDecl);
159 if (
const NamedDecl *
Result = Visitor.getNamedDecl()) {
169 const std::string &
Name) {
170 const auto &
SourceMgr = Context.getSourceManager();
171 NamedDeclFindingASTVisitor Visitor(
SourceMgr, Name);
172 auto Decls = Context.getTranslationUnitDecl()->decls();
174 for (
auto &CurrDecl : Decls) {
175 Visitor.TraverseDecl(CurrDecl);
176 if (
const NamedDecl *
Result = Visitor.getNamedDecl()) {
185 llvm::SmallVector<char, 128> Buff;
188 if (Decl ==
nullptr || index::generateUSRForDecl(Decl, Buff))
191 return std::string(Buff.data(), Buff.size());
SourceLocation Loc
'#' location in the include directive
const SourceLocation Point
const NamedDecl * getNamedDeclAt(const ASTContext &Context, const SourceLocation Point)
std::string getUSRForDecl(const Decl *Decl)
Methods for determining the USR of a symbol at a location in source code.
const NamedDecl * getNamedDeclFor(const ASTContext &Context, const std::string &Name)
const SourceManager & SourceMgr
ClangTidyContext & Context