#include "clang/Tooling/Refactoring/Rename/USRFinder.h"
#include "clang/AST/AST.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Index/USRGeneration.h"
#include "clang/Lex/Lexer.h"
#include "clang/Tooling/Refactoring/RecursiveSymbolVisitor.h"
#include "llvm/ADT/SmallVector.h"
using namespace llvm;
namespace clang {
namespace tooling {
namespace {
class NamedDeclOccurrenceFindingVisitor
: public RecursiveSymbolVisitor<NamedDeclOccurrenceFindingVisitor> {
public:
explicit NamedDeclOccurrenceFindingVisitor(const SourceLocation Point,
const ASTContext &Context)
: RecursiveSymbolVisitor(Context.getSourceManager(),
Context.getLangOpts()),
Point(Point), Context(Context) {}
bool visitSymbolOccurrence(const NamedDecl *ND,
ArrayRef<SourceRange> NameRanges) {
if (!ND)
return true;
for (const auto &Range : NameRanges) {
SourceLocation Start = Range.getBegin();
SourceLocation End = Range.getEnd();
if (!Start.isValid() || !Start.isFileID() || !End.isValid() ||
!End.isFileID() || !isPointWithin(Start, End))
return true;
}
Result = ND;
return false;
}
const NamedDecl *getNamedDecl() const { return Result; }
private:
bool isPointWithin(const SourceLocation Start, const SourceLocation End) {
return Point == Start || Point == End ||
(Context.getSourceManager().isBeforeInTranslationUnit(Start,
Point) &&
Context.getSourceManager().isBeforeInTranslationUnit(Point, End));
}
const NamedDecl *Result = nullptr;
const SourceLocation Point;
const ASTContext &Context;
};
}
const NamedDecl *getNamedDeclAt(const ASTContext &Context,
const SourceLocation Point) {
const SourceManager &SM = Context.getSourceManager();
NamedDeclOccurrenceFindingVisitor Visitor(Point, Context);
for (auto *CurrDecl : Context.getTranslationUnitDecl()->decls()) {
SourceLocation StartLoc = CurrDecl->getBeginLoc();
SourceLocation EndLoc = CurrDecl->getEndLoc();
if (StartLoc.isValid() && EndLoc.isValid() &&
SM.isBeforeInTranslationUnit(StartLoc, Point) !=
SM.isBeforeInTranslationUnit(EndLoc, Point))
Visitor.TraverseDecl(CurrDecl);
}
return Visitor.getNamedDecl();
}
namespace {
class NamedDeclFindingVisitor
: public RecursiveASTVisitor<NamedDeclFindingVisitor> {
public:
explicit NamedDeclFindingVisitor(StringRef Name) : Name(Name) {}
bool VisitNamedDecl(const NamedDecl *ND) {
if (!ND)
return true;
if (Name != ND->getQualifiedNameAsString() &&
Name != "::" + ND->getQualifiedNameAsString())
return true;
Result = ND;
return false;
}
const NamedDecl *getNamedDecl() const { return Result; }
private:
const NamedDecl *Result = nullptr;
StringRef Name;
};
}
const NamedDecl *getNamedDeclFor(const ASTContext &Context,
const std::string &Name) {
NamedDeclFindingVisitor Visitor(Name);
Visitor.TraverseDecl(Context.getTranslationUnitDecl());
return Visitor.getNamedDecl();
}
std::string getUSRForDecl(const Decl *Decl) {
llvm::SmallString<128> Buff;
if (Decl == nullptr || index::generateUSRForDecl(Decl, Buff))
return "";
return std::string(Buff);
}
}
}