clang-tools  3.8.0
USRFindingAction.cpp
Go to the documentation of this file.
1 //===--- tools/extra/clang-rename/USRFindingAction.cpp - Clang rename tool ===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief Provides an action to rename every symbol at a point.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #include "USRFindingAction.h"
16 #include "USRFinder.h"
17 #include "clang/AST/AST.h"
18 #include "clang/AST/ASTConsumer.h"
19 #include "clang/AST/ASTContext.h"
20 #include "clang/Basic/FileManager.h"
21 #include "clang/Frontend/CompilerInstance.h"
22 #include "clang/Frontend/FrontendAction.h"
23 #include "clang/Lex/Lexer.h"
24 #include "clang/Lex/Preprocessor.h"
25 #include "clang/Tooling/CommonOptionsParser.h"
26 #include "clang/Tooling/Refactoring.h"
27 #include "clang/Tooling/Tooling.h"
28 #include <ctype.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string>
32 #include <vector>
33 
34 using namespace llvm;
35 
36 namespace clang {
37 namespace rename {
38 
39 // Get the USRs for the constructors of the class.
40 static std::vector<std::string> getAllConstructorUSRs(
41  const CXXRecordDecl *Decl) {
42  std::vector<std::string> USRs;
43 
44  // We need to get the definition of the record (as opposed to any forward
45  // declarations) in order to find the constructor and destructor.
46  const auto *RecordDecl = Decl->getDefinition();
47 
48  // Iterate over all the constructors and add their USRs.
49  for (const auto *CtorDecl : RecordDecl->ctors())
50  USRs.push_back(getUSRForDecl(CtorDecl));
51 
52  // Ignore destructors. GetLocationsOfUSR will find the declaration of and
53  // explicit calls to a destructor through TagTypeLoc (and it is better for the
54  // purpose of renaming).
55  //
56  // For example, in the following code segment,
57  // 1 class C {
58  // 2 ~C();
59  // 3 };
60  // At line 3, there is a NamedDecl starting from '~' and a TagTypeLoc starting
61  // from 'C'.
62 
63  return USRs;
64 }
65 
67  void HandleTranslationUnit(ASTContext &Context) override {
68  const auto &SourceMgr = Context.getSourceManager();
69  // The file we look for the USR in will always be the main source file.
70  const auto Point = SourceMgr.getLocForStartOfFile(
71  SourceMgr.getMainFileID()).getLocWithOffset(SymbolOffset);
72  if (!Point.isValid())
73  return;
74  const NamedDecl *FoundDecl = getNamedDeclAt(Context, Point);
75  if (FoundDecl == nullptr) {
76  FullSourceLoc FullLoc(Point, SourceMgr);
77  errs() << "clang-rename: could not find symbol at "
78  << SourceMgr.getFilename(Point) << ":"
79  << FullLoc.getSpellingLineNumber() << ":"
80  << FullLoc.getSpellingColumnNumber() << " (offset " << SymbolOffset
81  << ").\n";
82  return;
83  }
84 
85  // If the decl is a constructor or destructor, we want to instead take the
86  // decl of the parent record.
87  if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(FoundDecl))
88  FoundDecl = CtorDecl->getParent();
89  else if (const auto *DtorDecl = dyn_cast<CXXDestructorDecl>(FoundDecl))
90  FoundDecl = DtorDecl->getParent();
91 
92  // If the decl is in any way relatedpp to a class, we want to make sure we
93  // search for the constructor and destructor as well as everything else.
94  if (const auto *Record = dyn_cast<CXXRecordDecl>(FoundDecl))
95  *USRs = getAllConstructorUSRs(Record);
96 
97  USRs->push_back(getUSRForDecl(FoundDecl));
98  *SpellingName = FoundDecl->getNameAsString();
99  }
100 
101  unsigned SymbolOffset;
102  std::string *SpellingName;
103  std::vector<std::string> *USRs;
104 };
105 
106 std::unique_ptr<ASTConsumer>
107 USRFindingAction::newASTConsumer() {
108  std::unique_ptr<NamedDeclFindingConsumer> Consumer(
110  SpellingName = "";
111  Consumer->SymbolOffset = SymbolOffset;
112  Consumer->USRs = &USRs;
113  Consumer->SpellingName = &SpellingName;
114  return std::move(Consumer);
115 }
116 
117 } // namespace rename
118 } // namespace clang
const SourceLocation Point
Definition: USRFinder.cpp:123
const NamedDecl * getNamedDeclAt(const ASTContext &Context, const SourceLocation Point)
Definition: USRFinder.cpp:127
std::string getUSRForDecl(const Decl *Decl)
Definition: USRFinder.cpp:151
SourceManager SourceMgr
Definition: ClangTidy.cpp:172
Provides an action to find all relevent USRs at a point.
Methods for determining the USR of a symbol at a location in source code.
void HandleTranslationUnit(ASTContext &Context) override
static cl::opt< unsigned > SymbolOffset("offset", cl::desc("Locates the symbol by offset as opposed to <line>:<column>."), cl::cat(ClangRenameCategory))
static std::vector< std::string > getAllConstructorUSRs(const CXXRecordDecl *Decl)
ClangTidyContext & Context
Definition: ClangTidy.cpp:93