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 SourceLocation
Point,
39 :
Result(nullptr), Point(Point), Context(Context) {}
43 explicit NamedDeclFindingASTVisitor(
const std::string &
Name,
45 :
Result(nullptr), Name(Name), Context(Context) {}
53 bool VisitNamedDecl(
const NamedDecl *Decl) {
54 return dyn_cast<CXXConversionDecl>(Decl)
56 : setResult(Decl, Decl->getLocation(),
57 Decl->getNameAsString().length());
62 bool VisitDeclRefExpr(
const DeclRefExpr *Expr) {
63 const NamedDecl *Decl = Expr->getFoundDecl();
64 return setResult(Decl, Expr->getLocation(),
65 Decl->getNameAsString().length());
68 bool VisitMemberExpr(
const MemberExpr *Expr) {
69 const NamedDecl *Decl = Expr->getFoundDecl().getDecl();
70 return setResult(Decl, Expr->getMemberLoc(),
71 Decl->getNameAsString().length());
76 bool VisitTypeLoc(
const TypeLoc
Loc) {
77 const SourceLocation TypeBeginLoc = Loc.getBeginLoc();
78 const SourceLocation TypeEndLoc = Lexer::getLocForEndOfToken(
79 TypeBeginLoc, 0,
Context.getSourceManager(),
Context.getLangOpts());
80 if (
const auto *TemplateTypeParm =
81 dyn_cast<TemplateTypeParmType>(Loc.getType()))
82 return setResult(TemplateTypeParm->getDecl(), TypeBeginLoc, TypeEndLoc);
83 if (
const auto *TemplateSpecType =
84 dyn_cast<TemplateSpecializationType>(Loc.getType())) {
85 return setResult(TemplateSpecType->getTemplateName().getAsTemplateDecl(),
86 TypeBeginLoc, TypeEndLoc);
88 return setResult(Loc.getType()->getAsCXXRecordDecl(), TypeBeginLoc,
92 bool VisitCXXConstructorDecl(clang::CXXConstructorDecl *ConstructorDecl) {
93 for (
const auto *Initializer : ConstructorDecl->inits()) {
95 if (!Initializer->isWritten())
97 if (
const clang::FieldDecl *FieldDecl = Initializer->getMember()) {
98 const SourceLocation InitBeginLoc = Initializer->getSourceLocation(),
99 InitEndLoc = Lexer::getLocForEndOfToken(
100 InitBeginLoc, 0,
Context.getSourceManager(),
102 if (!setResult(FieldDecl, InitBeginLoc, InitEndLoc))
111 const NamedDecl *getNamedDecl() {
return Result; }
115 void handleNestedNameSpecifierLoc(NestedNameSpecifierLoc NameLoc) {
117 const NamespaceDecl *Decl =
118 NameLoc.getNestedNameSpecifier()->getAsNamespace();
119 setResult(Decl, NameLoc.getLocalBeginLoc(), NameLoc.getLocalEndLoc());
120 NameLoc = NameLoc.getPrefix();
127 bool setResult(
const NamedDecl *Decl, SourceLocation Start,
128 SourceLocation End) {
133 if (!Start.isValid() || !Start.isFileID() || !End.isValid() ||
134 !End.isFileID() || !isPointWithin(Start, End))
138 if (
Name != Decl->getQualifiedNameAsString())
147 bool setResult(
const NamedDecl *Decl, SourceLocation Loc,
unsigned Offset) {
149 return Offset == 0 ||
150 setResult(Decl, Loc, Loc.getLocWithOffset(Offset - 1));
154 bool isPointWithin(
const SourceLocation Start,
const SourceLocation End) {
157 (
Context.getSourceManager().isBeforeInTranslationUnit(Start,
159 Context.getSourceManager().isBeforeInTranslationUnit(
Point, End));
170 const SourceLocation
Point) {
171 const SourceManager &
SM = Context.getSourceManager();
172 NamedDeclFindingASTVisitor Visitor(Point, Context);
177 for (
auto *CurrDecl : Context.getTranslationUnitDecl()->decls()) {
178 SourceLocation StartLoc = CurrDecl->getLocStart();
179 SourceLocation EndLoc = CurrDecl->getLocEnd();
180 if (StartLoc.isValid() && EndLoc.isValid() &&
181 SM.isBeforeInTranslationUnit(StartLoc, Point) !=
182 SM.isBeforeInTranslationUnit(EndLoc, Point))
183 Visitor.TraverseDecl(CurrDecl);
188 Visitor.handleNestedNameSpecifierLoc(
Location);
190 return Visitor.getNamedDecl();
194 const std::string &
Name) {
195 NamedDeclFindingASTVisitor Visitor(Name, Context);
196 Visitor.TraverseDecl(Context.getTranslationUnitDecl());
198 return Visitor.getNamedDecl();
202 llvm::SmallVector<char, 128> Buff;
205 if (Decl ==
nullptr || index::generateUSRForDecl(Decl, Buff))
208 return std::string(Buff.data(), Buff.size());
SourceLocation Loc
'#' location in the include directive
const SourceLocation Point
std::unique_ptr< ast_matchers::MatchFinder > Finder
const NamedDecl * getNamedDeclAt(const ASTContext &Context, const SourceLocation Point)
std::string getUSRForDecl(const Decl *Decl)
const ASTContext & Context
Methods for determining the USR of a symbol at a location in source code.
const NamedDecl * getNamedDeclFor(const ASTContext &Context, const std::string &Name)
std::vector< NestedNameSpecifierLoc > getNestedNameSpecifierLocations()