clang-tools 3.8.0

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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
66 struct NamedDeclFindingConsumer : public ASTConsumer {
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(
109 new NamedDeclFindingConsumer);
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
Point
const SourceLocation Point
Definition: USRFinder.cpp:123
clang::rename::NamedDeclFindingConsumer
Definition: USRFindingAction.cpp:66
clang::rename::NamedDeclFindingConsumer::SpellingName
std::string * SpellingName
Definition: USRFindingAction.cpp:102
clang::rename::getNamedDeclAt
const NamedDecl * getNamedDeclAt(const ASTContext &Context, const SourceLocation Point)
Definition: USRFinder.cpp:127
clang::rename::getUSRForDecl
std::string getUSRForDecl(const Decl *Decl)
Definition: USRFinder.cpp:151
SourceMgr
SourceManager SourceMgr
Definition: ClangTidy.cpp:172
USRFindingAction.h
Provides an action to find all relevent USRs at a point.
USRFinder.h
Methods for determining the USR of a symbol at a location in source code.
clang::rename::NamedDeclFindingConsumer::HandleTranslationUnit
void HandleTranslationUnit(ASTContext &Context) override
Definition: USRFindingAction.cpp:67
ASTConsumer
clang::rename::NamedDeclFindingConsumer::USRs
std::vector< std::string > * USRs
Definition: USRFindingAction.cpp:103
SymbolOffset
static cl::opt< unsigned > SymbolOffset("offset", cl::desc("Locates the symbol by offset as opposed to <line>:<column>."), cl::cat(ClangRenameCategory))
clang::rename::NamedDeclFindingConsumer::SymbolOffset
unsigned SymbolOffset
Definition: USRFindingAction.cpp:101
clang::rename::getAllConstructorUSRs
static std::vector< std::string > getAllConstructorUSRs(const CXXRecordDecl *Decl)
Definition: USRFindingAction.cpp:40
Context
ClangTidyContext & Context
Definition: ClangTidy.cpp:93