forked from llvm-mirror/clang
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[refactor][rename] Use a single base class for class that finds
a declaration at location and for class that searches for all occurrences of a specific declaration This commit uses a single RecursiveSymbolVisitor class for both USRLocFindingASTVisitor and NamedDeclOccurrenceFindingVisitor to avoid duplicate traversal code. It also traverses nested name specifier locs in the new class and remove the separate matching step. Differential Revision: https://reviews.llvm.org/D34949 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@307898 91177308-0d34-0410-b5e6-96231b3b80d8
- Loading branch information
Showing
5 changed files
with
196 additions
and
230 deletions.
There are no files selected for viewing
124 changes: 124 additions & 0 deletions
124
include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
//===--- RecursiveSymbolVisitor.h - Clang refactoring library -------------===// | ||
// | ||
// The LLVM Compiler Infrastructure | ||
// | ||
// This file is distributed under the University of Illinois Open Source | ||
// License. See LICENSE.TXT for details. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
/// | ||
/// \file | ||
/// \brief A wrapper class around \c RecursiveASTVisitor that visits each | ||
/// occurrences of a named symbol. | ||
/// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_CLANG_TOOLING_REFACTOR_RECURSIVE_SYMBOL_VISITOR_H | ||
#define LLVM_CLANG_TOOLING_REFACTOR_RECURSIVE_SYMBOL_VISITOR_H | ||
|
||
#include "clang/AST/AST.h" | ||
#include "clang/AST/RecursiveASTVisitor.h" | ||
#include "clang/Lex/Lexer.h" | ||
|
||
using namespace llvm; | ||
|
||
namespace clang { | ||
namespace tooling { | ||
|
||
/// Traverses the AST and visits the occurrence of each named symbol in the | ||
/// given nodes. | ||
template <typename T> | ||
class RecursiveSymbolVisitor | ||
: public RecursiveASTVisitor<RecursiveSymbolVisitor<T>> { | ||
using BaseType = RecursiveASTVisitor<RecursiveSymbolVisitor<T>>; | ||
|
||
public: | ||
RecursiveSymbolVisitor(const SourceManager &SM, const LangOptions &LangOpts) | ||
: SM(SM), LangOpts(LangOpts) {} | ||
|
||
bool visitSymbolOccurrence(const NamedDecl *ND, | ||
ArrayRef<SourceRange> NameRanges) { | ||
return true; | ||
} | ||
|
||
// Declaration visitors: | ||
|
||
bool VisitNamedDecl(const NamedDecl *D) { | ||
return isa<CXXConversionDecl>(D) ? true : visit(D, D->getLocation()); | ||
} | ||
|
||
bool VisitCXXConstructorDecl(const CXXConstructorDecl *CD) { | ||
for (const auto *Initializer : CD->inits()) { | ||
// Ignore implicit initializers. | ||
if (!Initializer->isWritten()) | ||
continue; | ||
if (const FieldDecl *FD = Initializer->getMember()) { | ||
if (!visit(FD, Initializer->getSourceLocation(), | ||
Lexer::getLocForEndOfToken(Initializer->getSourceLocation(), | ||
0, SM, LangOpts))) | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
// Expression visitors: | ||
|
||
bool VisitDeclRefExpr(const DeclRefExpr *Expr) { | ||
return visit(Expr->getFoundDecl(), Expr->getLocation()); | ||
} | ||
|
||
bool VisitMemberExpr(const MemberExpr *Expr) { | ||
return visit(Expr->getFoundDecl().getDecl(), Expr->getMemberLoc()); | ||
} | ||
|
||
// Other visitors: | ||
|
||
bool VisitTypeLoc(const TypeLoc Loc) { | ||
const SourceLocation TypeBeginLoc = Loc.getBeginLoc(); | ||
const SourceLocation TypeEndLoc = | ||
Lexer::getLocForEndOfToken(TypeBeginLoc, 0, SM, LangOpts); | ||
if (const auto *TemplateTypeParm = | ||
dyn_cast<TemplateTypeParmType>(Loc.getType())) { | ||
if (!visit(TemplateTypeParm->getDecl(), TypeBeginLoc, TypeEndLoc)) | ||
return false; | ||
} | ||
if (const auto *TemplateSpecType = | ||
dyn_cast<TemplateSpecializationType>(Loc.getType())) { | ||
if (!visit(TemplateSpecType->getTemplateName().getAsTemplateDecl(), | ||
TypeBeginLoc, TypeEndLoc)) | ||
return false; | ||
} | ||
return visit(Loc.getType()->getAsCXXRecordDecl(), TypeBeginLoc, TypeEndLoc); | ||
} | ||
|
||
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { | ||
// The base visitor will visit NNSL prefixes, so we should only look at | ||
// the current NNS. | ||
if (NNS) { | ||
const NamespaceDecl *ND = NNS.getNestedNameSpecifier()->getAsNamespace(); | ||
if (!visit(ND, NNS.getLocalBeginLoc(), NNS.getLocalEndLoc())) | ||
return false; | ||
} | ||
return BaseType::TraverseNestedNameSpecifierLoc(NNS); | ||
} | ||
|
||
private: | ||
const SourceManager &SM; | ||
const LangOptions &LangOpts; | ||
|
||
bool visit(const NamedDecl *ND, SourceLocation BeginLoc, | ||
SourceLocation EndLoc) { | ||
return static_cast<T *>(this)->visitSymbolOccurrence( | ||
ND, SourceRange(BeginLoc, EndLoc)); | ||
} | ||
bool visit(const NamedDecl *ND, SourceLocation Loc) { | ||
return visit(ND, Loc, | ||
Loc.getLocWithOffset(ND->getNameAsString().length() - 1)); | ||
} | ||
}; | ||
|
||
} // end namespace tooling | ||
} // end namespace clang | ||
|
||
#endif // LLVM_CLANG_TOOLING_REFACTOR_RECURSIVE_SYMBOL_VISITOR_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.