clang: lib/Tooling/Refactoring/Rename/RenamingAction.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

32#include "llvm/ADT/STLExtras.h"

33#include "llvm/Support/Errc.h"

34#include "llvm/Support/Error.h"

35#include

36#include

37

38using namespace llvm;

39

41namespace tooling {

42

43namespace {

44

46findSymbolOccurrences(const NamedDecl *ND, RefactoringRuleContext &Context) {

47 std::vectorstd::string USRs =

49 std::string PrevName = ND->getNameAsString();

51 Context.getASTContext().getTranslationUnitDecl());

52}

53

54}

55

58 "local-rename",

59 "Rename",

60 "Finds and renames symbols in code with no indexer support",

61 };

62 return Descriptor;

63}

64

67 SourceRange SelectionRange, std::string NewName) {

70 if (!ND)

71 return Context.createDiagnosticError(

72 SelectionRange.getBegin(), diag::err_refactor_selection_no_symbol);

74 std::move(NewName));

75}

76

78

82 if (!Occurrences)

83 return Occurrences.takeError();

84

87 *Occurrences, Context.getASTContext().getSourceManager(), Name);

88}

89

92 std::string OldQualifiedName,

93 std::string NewQualifiedName) {

95 getNamedDeclFor(Context.getASTContext(), OldQualifiedName);

96 if (!ND)

97 return llvm::make_errorllvm::StringError("Could not find symbol " +

98 OldQualifiedName,

99 llvm::errc::invalid_argument);

101}

102

105 "local-qualified-rename",

106 "Qualified Rename",

107

108 R"(Finds and renames qualified symbols in code within a translation unit.

109It is used to move/rename a symbol to a new namespace/name:

110 * Supported symbols: classes, class members, functions, enums, and type alias.

111 * Renames all symbol occurrences from the old qualified name to the new

112 qualified name. All symbol references will be correctly qualified; For

113 symbol definitions, only name will be changed.

114For example, rename "A::Foo" to "B::Bar":

115 Old code:

116 namespace foo {

117 class A {};

118 }

119

120 namespace bar {

121 void f(foo::A a) {}

123

124 New code after rename:

125 namespace foo {

126 class B {};

127 }

128

129 namespace bar {

130 void f(B b) {}

131 })"

132 };

133 return Descriptor;

134}

135

137QualifiedRenameRule::createSourceReplacements(RefactoringRuleContext &Context) {

139 assert(!USRs.empty());

141 USRs, NewQualifiedName, Context.getASTContext().getTranslationUnitDecl());

142}

143

147

148 std::vector Changes;

149 for (const auto &Occurrence : Occurrences) {

151 assert(NewName.getNamePieces().size() == Ranges.size() &&

152 "Mismatching number of ranges and name pieces");

154 for (const auto &Range : llvm::enumerate(Ranges)) {

155 auto Error =

158 if (Error)

159 return std::move(Error);

161 Changes.push_back(std::move(Change));

163 return std::move(Changes);

164}

165

166

167

170 std::map<std::string, tooling::Replacements> *FileToReplaces) {

173 llvm::Error Err =

174 (*FileToReplaces)[std::string(Replace.getFilePath())].add(Replace);

175 if (Err) {

176 llvm::errs() << "Renaming failed in " << Replace.getFilePath() << "! "

177 << llvm::toString(std::move(Err)) << "\n";

178 }

179 }

180 }

182

184public:

186 const std::vectorstd::string &NewNames,

187 const std::vectorstd::string &PrevNames,

188 const std::vector<std::vectorstd::string> &USRList,

189 std::map<std::string, tooling::Replacements> &FileToReplaces,

190 bool PrintLocations)

191 : NewNames(NewNames), PrevNames(PrevNames), USRList(USRList),

192 FileToReplaces(FileToReplaces), PrintLocations(PrintLocations) {}

193

195 for (unsigned I = 0; I < NewNames.size(); ++I) {

196

197 if (PrevNames[I].empty())

198 continue;

199

200 HandleOneRename(Context, NewNames[I], PrevNames[I], USRList[I]);

201 }

202 }

203

204 void HandleOneRename(ASTContext &Context, const std::string &NewName,

205 const std::string &PrevName,

206 const std::vectorstd::string &USRs) {

207 const SourceManager &SourceMgr = Context.getSourceManager();

208

210 USRs, PrevName, Context.getTranslationUnitDecl());

211 if (PrintLocations) {

212 for (const auto &Occurrence : Occurrences) {

213 FullSourceLoc FullLoc(Occurrence.getNameRanges()[0].getBegin(),

214 SourceMgr);

215 errs() << "clang-rename: renamed at: " << SourceMgr.getFilename(FullLoc)

216 << ":" << FullLoc.getSpellingLineNumber() << ":"

217 << FullLoc.getSpellingColumnNumber() << "\n";

218 }

219 }

220

221

225 if (!Change) {

226 llvm::errs() << "Failed to create renaming replacements for '" << PrevName

227 << "'! " << llvm::toString(Change.takeError()) << "\n";

228 return;

229 }

231 }

232

233private:

234 const std::vectorstd::string &NewNames, &PrevNames;

235 const std::vector<std::vectorstd::string> &USRList;

236 std::map<std::string, tooling::Replacements> &FileToReplaces;

237 bool PrintLocations;

238};

239

240

241

242

243

244class USRSymbolRenamer : public ASTConsumer {

245public:

247 const std::vector<std::vectorstd::string> &USRList,

248 std::map<std::string, tooling::Replacements> &FileToReplaces)

249 : NewNames(NewNames), USRList(USRList), FileToReplaces(FileToReplaces) {

250 assert(USRList.size() == NewNames.size());

252

254 for (unsigned I = 0; I < NewNames.size(); ++I) {

255

256

258 USRList[I], NewNames[I], Context.getTranslationUnitDecl());

260 }

261 }

262

263private:

264 const std::vectorstd::string &NewNames;

265 const std::vector<std::vectorstd::string> &USRList;

266 std::map<std::string, tooling::Replacements> &FileToReplaces;

267};

268

270 return std::make_unique(NewNames, PrevNames, USRList,

271 FileToReplaces, PrintLocations);

272}

273

275 return std::make_unique(NewNames, USRList, FileToReplaces);

276}

277

278}

279}

Defines the clang::ASTContext interface.

Defines the clang::FileManager interface and associated types.

Defines the clang::FrontendAction interface and various convenience abstract classes (clang::ASTFront...

Defines the clang::Preprocessor interface.

Provides an action to rename every symbol at a point.

Methods for determining the USR of a symbol at a location in source code.

Provides an action to find all relevant USRs at a point.

Provides functionality for finding all instances of a USR in a given AST.

ASTConsumer - This is an abstract interface that should be implemented by clients that read ASTs.

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

static CharSourceRange getCharRange(SourceRange R)

This represents a decl that may have a name.

This class handles loading and caching of source files into memory.

A trivial tuple used to represent a source range.

SourceLocation getBegin() const

The refactoring rule context stores all of the inputs that might be needed by a refactoring action ru...

The JSON file list parser is used to communicate input to InstallAPI.

Diagnostic wrappers for TextAPI types for error reporting.