blob: da9256282f0c3cc9834edb5658b47433d544561e [file] [log] [blame]
Manuel Klimekde237262014-08-20 01:39:05 +00001//===--- 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"
Manuel Klimekde237262014-08-20 01:39:05 +000023#include "clang/Lex/Lexer.h"
Chandler Carruth3cbd71c2015-01-14 11:24:38 +000024#include "clang/Lex/Preprocessor.h"
Manuel Klimekde237262014-08-20 01:39:05 +000025#include "clang/Tooling/CommonOptionsParser.h"
26#include "clang/Tooling/Refactoring.h"
27#include "clang/Tooling/Tooling.h"
Chandler Carruth3cbd71c2015-01-14 11:24:38 +000028#include <ctype.h>
Manuel Klimekde237262014-08-20 01:39:05 +000029#include <stdio.h>
30#include <stdlib.h>
Manuel Klimekde237262014-08-20 01:39:05 +000031#include <string>
32#include <vector>
33
34using namespace llvm;
35
36namespace clang {
37namespace rename {
38
39// Get the USRs for the constructors of the class.
40static 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.
Richard Trieua60ca812015-04-15 01:21:57 +000049 for (const auto *CtorDecl : RecordDecl->ctors())
Manuel Klimekde237262014-08-20 01:39:05 +000050 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
66struct 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
106std::unique_ptr<ASTConsumer>
107USRFindingAction::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