Skip to content

Commit

Permalink
[refactor][rename] Use a single base class for class that finds
Browse files Browse the repository at this point in the history
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
hyp committed Jul 13, 2017
1 parent f37177d commit ffd7020
Show file tree
Hide file tree
Showing 5 changed files with 196 additions and 230 deletions.
124 changes: 124 additions & 0 deletions include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
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
32 changes: 0 additions & 32 deletions include/clang/Tooling/Refactoring/Rename/USRFinder.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,10 @@

#include "clang/AST/AST.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include <string>
#include <vector>

using namespace llvm;
using namespace clang::ast_matchers;

namespace clang {

Expand All @@ -48,36 +46,6 @@ const NamedDecl *getNamedDeclFor(const ASTContext &Context,
// Converts a Decl into a USR.
std::string getUSRForDecl(const Decl *Decl);

// FIXME: Implement RecursiveASTVisitor<T>::VisitNestedNameSpecifier instead.
class NestedNameSpecifierLocFinder : public MatchFinder::MatchCallback {
public:
explicit NestedNameSpecifierLocFinder(ASTContext &Context)
: Context(Context) {}

std::vector<NestedNameSpecifierLoc> getNestedNameSpecifierLocations() {
addMatchers();
Finder.matchAST(Context);
return Locations;
}

private:
void addMatchers() {
const auto NestedNameSpecifierLocMatcher =
nestedNameSpecifierLoc().bind("nestedNameSpecifierLoc");
Finder.addMatcher(NestedNameSpecifierLocMatcher, this);
}

void run(const MatchFinder::MatchResult &Result) override {
const auto *NNS = Result.Nodes.getNodeAs<NestedNameSpecifierLoc>(
"nestedNameSpecifierLoc");
Locations.push_back(*NNS);
}

ASTContext &Context;
std::vector<NestedNameSpecifierLoc> Locations;
MatchFinder Finder;
};

} // end namespace tooling
} // end namespace clang

Expand Down
1 change: 0 additions & 1 deletion include/clang/module.modulemap
Original file line number Diff line number Diff line change
Expand Up @@ -138,5 +138,4 @@ module Clang_Tooling {
// importing the AST matchers library gives a link dependency on the AST
// matchers (and thus the AST), which clang-format should not have.
exclude header "Tooling/RefactoringCallbacks.h"
exclude header "Tooling/Refactoring/Rename/USRFinder.h"
}
Loading

0 comments on commit ffd7020

Please sign in to comment.