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

1

2

3

4

5

6

7

8

9

10

11

12

13

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

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

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

26#include

27#include

28

29using namespace llvm;

30

33

34namespace {

35

38 std::vectorstd::string USRs =

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

43}

44

45}

46

49 "local-rename",

50 "Rename",

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

52 };

53 return Descriptor;

54}

55

58 SourceRange SelectionRange, std::string NewName) {

61 if (!ND)

62 return Context.createDiagnosticError(

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

65 std::move(NewName));

66}

67

69

73 if (!Occurrences)

74 return Occurrences.takeError();

75

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

79}

80

83 std::string OldQualifiedName,

84 std::string NewQualifiedName) {

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

87 if (!ND)

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

89 OldQualifiedName,

90 llvm::errc::invalid_argument);

91 return QualifiedRenameRule(ND, std::move(NewQualifiedName));

92}

93

96 "local-qualified-rename",

97 "Qualified Rename",

98

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

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

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

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

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

104 symbol definitions, only name will be changed.

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

106 Old code:

107 namespace foo {

108 class A {};

109 }

110

111 namespace bar {

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

114

115 New code after rename:

116 namespace foo {

117 class B {};

118 }

119

120 namespace bar {

121 void f(B b) {}

122 })"

123 };

124 return Descriptor;

125}

126

128QualifiedRenameRule::createSourceReplacements(RefactoringRuleContext &Context) {

130 assert(!USRs.empty());

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

133}

134

138

139 std::vector Changes;

140 for (const auto &Occurrence : Occurrences) {

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

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

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

150 return std::move(Error);

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

154 return std::move(Changes);

155}

156

157

158

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

164 llvm::Error Err =

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

166 if (Err) {

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

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

169 }

170 }

171 }

173

175public:

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

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

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

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

181 bool PrintLocations)

182 : NewNames(NewNames), PrevNames(PrevNames), USRList(USRList),

183 FileToReplaces(FileToReplaces), PrintLocations(PrintLocations) {}

184

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

187

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

189 continue;

190

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

192 }

193 }

194

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

196 const std::string &PrevName,

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

199

202 if (PrintLocations) {

203 for (const auto &Occurrence : Occurrences) {

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

205 SourceMgr);

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

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

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

209 }

210 }

211

212

216 if (!Change) {

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

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

219 return;

220 }

222 }

223

224private:

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

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

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

228 bool PrintLocations;

229};

230

231

232

233

234

235class USRSymbolRenamer : public ASTConsumer {

236public:

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

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

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

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

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

246

247

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

251 }

252 }

253

254private:

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

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

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

258};

259

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

262 FileToReplaces, PrintLocations);

263}

264

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

267}

268

269}

270}

Defines the clang::ASTContext 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.

SourceManager & getSourceManager()

TranslationUnitDecl * getTranslationUnitDecl() const

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)

ASTContext & getASTContext() const LLVM_READONLY

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.