USRLocFinder.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. //===--- USRLocFinder.cpp - Clang refactoring library ---------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. ///
  9. /// \file
  10. /// Methods for finding all instances of a USR. Our strategy is very
  11. /// simple; we just compare the USR at every relevant AST node with the one
  12. /// provided.
  13. ///
  14. //===----------------------------------------------------------------------===//
  15. #include "clang/Tooling/Refactoring/Rename/USRLocFinder.h"
  16. #include "clang/AST/ASTContext.h"
  17. #include "clang/AST/ParentMapContext.h"
  18. #include "clang/AST/RecursiveASTVisitor.h"
  19. #include "clang/Basic/LLVM.h"
  20. #include "clang/Basic/SourceLocation.h"
  21. #include "clang/Basic/SourceManager.h"
  22. #include "clang/Lex/Lexer.h"
  23. #include "clang/Tooling/Refactoring/Lookup.h"
  24. #include "clang/Tooling/Refactoring/RecursiveSymbolVisitor.h"
  25. #include "clang/Tooling/Refactoring/Rename/SymbolName.h"
  26. #include "clang/Tooling/Refactoring/Rename/USRFinder.h"
  27. #include "llvm/ADT/StringRef.h"
  28. #include "llvm/Support/Casting.h"
  29. #include <cstddef>
  30. #include <set>
  31. #include <string>
  32. #include <vector>
  33. using namespace llvm;
  34. namespace clang {
  35. namespace tooling {
  36. namespace {
  37. // Returns true if the given Loc is valid for edit. We don't edit the
  38. // SourceLocations that are valid or in temporary buffer.
  39. bool IsValidEditLoc(const clang::SourceManager& SM, clang::SourceLocation Loc) {
  40. if (Loc.isInvalid())
  41. return false;
  42. const clang::FullSourceLoc FullLoc(Loc, SM);
  43. std::pair<clang::FileID, unsigned> FileIdAndOffset =
  44. FullLoc.getSpellingLoc().getDecomposedLoc();
  45. return SM.getFileEntryForID(FileIdAndOffset.first) != nullptr;
  46. }
  47. // This visitor recursively searches for all instances of a USR in a
  48. // translation unit and stores them for later usage.
  49. class USRLocFindingASTVisitor
  50. : public RecursiveSymbolVisitor<USRLocFindingASTVisitor> {
  51. public:
  52. explicit USRLocFindingASTVisitor(const std::vector<std::string> &USRs,
  53. StringRef PrevName,
  54. const ASTContext &Context)
  55. : RecursiveSymbolVisitor(Context.getSourceManager(),
  56. Context.getLangOpts()),
  57. USRSet(USRs.begin(), USRs.end()), PrevName(PrevName), Context(Context) {
  58. }
  59. bool visitSymbolOccurrence(const NamedDecl *ND,
  60. ArrayRef<SourceRange> NameRanges) {
  61. if (USRSet.find(getUSRForDecl(ND)) != USRSet.end()) {
  62. assert(NameRanges.size() == 1 &&
  63. "Multiple name pieces are not supported yet!");
  64. SourceLocation Loc = NameRanges[0].getBegin();
  65. const SourceManager &SM = Context.getSourceManager();
  66. // TODO: Deal with macro occurrences correctly.
  67. if (Loc.isMacroID())
  68. Loc = SM.getSpellingLoc(Loc);
  69. checkAndAddLocation(Loc);
  70. }
  71. return true;
  72. }
  73. // Non-visitors:
  74. /// Returns a set of unique symbol occurrences. Duplicate or
  75. /// overlapping occurrences are erroneous and should be reported!
  76. SymbolOccurrences takeOccurrences() { return std::move(Occurrences); }
  77. private:
  78. void checkAndAddLocation(SourceLocation Loc) {
  79. const SourceLocation BeginLoc = Loc;
  80. const SourceLocation EndLoc = Lexer::getLocForEndOfToken(
  81. BeginLoc, 0, Context.getSourceManager(), Context.getLangOpts());
  82. StringRef TokenName =
  83. Lexer::getSourceText(CharSourceRange::getTokenRange(BeginLoc, EndLoc),
  84. Context.getSourceManager(), Context.getLangOpts());
  85. size_t Offset = TokenName.find(PrevName.getNamePieces()[0]);
  86. // The token of the source location we find actually has the old
  87. // name.
  88. if (Offset != StringRef::npos)
  89. Occurrences.emplace_back(PrevName, SymbolOccurrence::MatchingSymbol,
  90. BeginLoc.getLocWithOffset(Offset));
  91. }
  92. const std::set<std::string> USRSet;
  93. const SymbolName PrevName;
  94. SymbolOccurrences Occurrences;
  95. const ASTContext &Context;
  96. };
  97. SourceLocation StartLocationForType(TypeLoc TL) {
  98. // For elaborated types (e.g. `struct a::A`) we want the portion after the
  99. // `struct` but including the namespace qualifier, `a::`.
  100. if (auto ElaboratedTypeLoc = TL.getAs<clang::ElaboratedTypeLoc>()) {
  101. NestedNameSpecifierLoc NestedNameSpecifier =
  102. ElaboratedTypeLoc.getQualifierLoc();
  103. if (NestedNameSpecifier.getNestedNameSpecifier())
  104. return NestedNameSpecifier.getBeginLoc();
  105. TL = TL.getNextTypeLoc();
  106. }
  107. return TL.getBeginLoc();
  108. }
  109. SourceLocation EndLocationForType(TypeLoc TL) {
  110. // Dig past any namespace or keyword qualifications.
  111. while (TL.getTypeLocClass() == TypeLoc::Elaborated ||
  112. TL.getTypeLocClass() == TypeLoc::Qualified)
  113. TL = TL.getNextTypeLoc();
  114. // The location for template specializations (e.g. Foo<int>) includes the
  115. // templated types in its location range. We want to restrict this to just
  116. // before the `<` character.
  117. if (TL.getTypeLocClass() == TypeLoc::TemplateSpecialization) {
  118. return TL.castAs<TemplateSpecializationTypeLoc>()
  119. .getLAngleLoc()
  120. .getLocWithOffset(-1);
  121. }
  122. return TL.getEndLoc();
  123. }
  124. NestedNameSpecifier *GetNestedNameForType(TypeLoc TL) {
  125. // Dig past any keyword qualifications.
  126. while (TL.getTypeLocClass() == TypeLoc::Qualified)
  127. TL = TL.getNextTypeLoc();
  128. // For elaborated types (e.g. `struct a::A`) we want the portion after the
  129. // `struct` but including the namespace qualifier, `a::`.
  130. if (auto ElaboratedTypeLoc = TL.getAs<clang::ElaboratedTypeLoc>())
  131. return ElaboratedTypeLoc.getQualifierLoc().getNestedNameSpecifier();
  132. return nullptr;
  133. }
  134. // Find all locations identified by the given USRs for rename.
  135. //
  136. // This class will traverse the AST and find every AST node whose USR is in the
  137. // given USRs' set.
  138. class RenameLocFinder : public RecursiveASTVisitor<RenameLocFinder> {
  139. public:
  140. RenameLocFinder(llvm::ArrayRef<std::string> USRs, ASTContext &Context)
  141. : USRSet(USRs.begin(), USRs.end()), Context(Context) {}
  142. // A structure records all information of a symbol reference being renamed.
  143. // We try to add as few prefix qualifiers as possible.
  144. struct RenameInfo {
  145. // The begin location of a symbol being renamed.
  146. SourceLocation Begin;
  147. // The end location of a symbol being renamed.
  148. SourceLocation End;
  149. // The declaration of a symbol being renamed (can be nullptr).
  150. const NamedDecl *FromDecl;
  151. // The declaration in which the nested name is contained (can be nullptr).
  152. const Decl *Context;
  153. // The nested name being replaced (can be nullptr).
  154. const NestedNameSpecifier *Specifier;
  155. // Determine whether the prefix qualifiers of the NewName should be ignored.
  156. // Normally, we set it to true for the symbol declaration and definition to
  157. // avoid adding prefix qualifiers.
  158. // For example, if it is true and NewName is "a::b::foo", then the symbol
  159. // occurrence which the RenameInfo points to will be renamed to "foo".
  160. bool IgnorePrefixQualifers;
  161. };
  162. bool VisitNamedDecl(const NamedDecl *Decl) {
  163. // UsingDecl has been handled in other place.
  164. if (llvm::isa<UsingDecl>(Decl))
  165. return true;
  166. // DestructorDecl has been handled in Typeloc.
  167. if (llvm::isa<CXXDestructorDecl>(Decl))
  168. return true;
  169. if (Decl->isImplicit())
  170. return true;
  171. if (isInUSRSet(Decl)) {
  172. // For the case of renaming an alias template, we actually rename the
  173. // underlying alias declaration of the template.
  174. if (const auto* TAT = dyn_cast<TypeAliasTemplateDecl>(Decl))
  175. Decl = TAT->getTemplatedDecl();
  176. auto StartLoc = Decl->getLocation();
  177. auto EndLoc = StartLoc;
  178. if (IsValidEditLoc(Context.getSourceManager(), StartLoc)) {
  179. RenameInfo Info = {StartLoc,
  180. EndLoc,
  181. /*FromDecl=*/nullptr,
  182. /*Context=*/nullptr,
  183. /*Specifier=*/nullptr,
  184. /*IgnorePrefixQualifers=*/true};
  185. RenameInfos.push_back(Info);
  186. }
  187. }
  188. return true;
  189. }
  190. bool VisitMemberExpr(const MemberExpr *Expr) {
  191. const NamedDecl *Decl = Expr->getFoundDecl();
  192. auto StartLoc = Expr->getMemberLoc();
  193. auto EndLoc = Expr->getMemberLoc();
  194. if (isInUSRSet(Decl)) {
  195. RenameInfos.push_back({StartLoc, EndLoc,
  196. /*FromDecl=*/nullptr,
  197. /*Context=*/nullptr,
  198. /*Specifier=*/nullptr,
  199. /*IgnorePrefixQualifiers=*/true});
  200. }
  201. return true;
  202. }
  203. bool VisitDesignatedInitExpr(const DesignatedInitExpr *E) {
  204. for (const DesignatedInitExpr::Designator &D : E->designators()) {
  205. if (D.isFieldDesignator() && D.getField()) {
  206. const FieldDecl *Decl = D.getField();
  207. if (isInUSRSet(Decl)) {
  208. auto StartLoc = D.getFieldLoc();
  209. auto EndLoc = D.getFieldLoc();
  210. RenameInfos.push_back({StartLoc, EndLoc,
  211. /*FromDecl=*/nullptr,
  212. /*Context=*/nullptr,
  213. /*Specifier=*/nullptr,
  214. /*IgnorePrefixQualifiers=*/true});
  215. }
  216. }
  217. }
  218. return true;
  219. }
  220. bool VisitCXXConstructorDecl(const CXXConstructorDecl *CD) {
  221. // Fix the constructor initializer when renaming class members.
  222. for (const auto *Initializer : CD->inits()) {
  223. // Ignore implicit initializers.
  224. if (!Initializer->isWritten())
  225. continue;
  226. if (const FieldDecl *FD = Initializer->getMember()) {
  227. if (isInUSRSet(FD)) {
  228. auto Loc = Initializer->getSourceLocation();
  229. RenameInfos.push_back({Loc, Loc,
  230. /*FromDecl=*/nullptr,
  231. /*Context=*/nullptr,
  232. /*Specifier=*/nullptr,
  233. /*IgnorePrefixQualifiers=*/true});
  234. }
  235. }
  236. }
  237. return true;
  238. }
  239. bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
  240. const NamedDecl *Decl = Expr->getFoundDecl();
  241. // Get the underlying declaration of the shadow declaration introduced by a
  242. // using declaration.
  243. if (auto *UsingShadow = llvm::dyn_cast<UsingShadowDecl>(Decl)) {
  244. Decl = UsingShadow->getTargetDecl();
  245. }
  246. auto StartLoc = Expr->getBeginLoc();
  247. // For template function call expressions like `foo<int>()`, we want to
  248. // restrict the end of location to just before the `<` character.
  249. SourceLocation EndLoc = Expr->hasExplicitTemplateArgs()
  250. ? Expr->getLAngleLoc().getLocWithOffset(-1)
  251. : Expr->getEndLoc();
  252. if (const auto *MD = llvm::dyn_cast<CXXMethodDecl>(Decl)) {
  253. if (isInUSRSet(MD)) {
  254. // Handle renaming static template class methods, we only rename the
  255. // name without prefix qualifiers and restrict the source range to the
  256. // name.
  257. RenameInfos.push_back({EndLoc, EndLoc,
  258. /*FromDecl=*/nullptr,
  259. /*Context=*/nullptr,
  260. /*Specifier=*/nullptr,
  261. /*IgnorePrefixQualifiers=*/true});
  262. return true;
  263. }
  264. }
  265. // In case of renaming an enum declaration, we have to explicitly handle
  266. // unscoped enum constants referenced in expressions (e.g.
  267. // "auto r = ns1::ns2::Green" where Green is an enum constant of an unscoped
  268. // enum decl "ns1::ns2::Color") as these enum constants cannot be caught by
  269. // TypeLoc.
  270. if (const auto *T = llvm::dyn_cast<EnumConstantDecl>(Decl)) {
  271. // FIXME: Handle the enum constant without prefix qualifiers (`a = Green`)
  272. // when renaming an unscoped enum declaration with a new namespace.
  273. if (!Expr->hasQualifier())
  274. return true;
  275. if (const auto *ED =
  276. llvm::dyn_cast_or_null<EnumDecl>(getClosestAncestorDecl(*T))) {
  277. if (ED->isScoped())
  278. return true;
  279. Decl = ED;
  280. }
  281. // The current fix would qualify "ns1::ns2::Green" as
  282. // "ns1::ns2::Color::Green".
  283. //
  284. // Get the EndLoc of the replacement by moving 1 character backward (
  285. // to exclude the last '::').
  286. //
  287. // ns1::ns2::Green;
  288. // ^ ^^
  289. // BeginLoc |EndLoc of the qualifier
  290. // new EndLoc
  291. EndLoc = Expr->getQualifierLoc().getEndLoc().getLocWithOffset(-1);
  292. assert(EndLoc.isValid() &&
  293. "The enum constant should have prefix qualifers.");
  294. }
  295. if (isInUSRSet(Decl) &&
  296. IsValidEditLoc(Context.getSourceManager(), StartLoc)) {
  297. RenameInfo Info = {StartLoc,
  298. EndLoc,
  299. Decl,
  300. getClosestAncestorDecl(*Expr),
  301. Expr->getQualifier(),
  302. /*IgnorePrefixQualifers=*/false};
  303. RenameInfos.push_back(Info);
  304. }
  305. return true;
  306. }
  307. bool VisitUsingDecl(const UsingDecl *Using) {
  308. for (const auto *UsingShadow : Using->shadows()) {
  309. if (isInUSRSet(UsingShadow->getTargetDecl())) {
  310. UsingDecls.push_back(Using);
  311. break;
  312. }
  313. }
  314. return true;
  315. }
  316. bool VisitNestedNameSpecifierLocations(NestedNameSpecifierLoc NestedLoc) {
  317. if (!NestedLoc.getNestedNameSpecifier()->getAsType())
  318. return true;
  319. if (const auto *TargetDecl =
  320. getSupportedDeclFromTypeLoc(NestedLoc.getTypeLoc())) {
  321. if (isInUSRSet(TargetDecl)) {
  322. RenameInfo Info = {NestedLoc.getBeginLoc(),
  323. EndLocationForType(NestedLoc.getTypeLoc()),
  324. TargetDecl,
  325. getClosestAncestorDecl(NestedLoc),
  326. NestedLoc.getNestedNameSpecifier()->getPrefix(),
  327. /*IgnorePrefixQualifers=*/false};
  328. RenameInfos.push_back(Info);
  329. }
  330. }
  331. return true;
  332. }
  333. bool VisitTypeLoc(TypeLoc Loc) {
  334. auto Parents = Context.getParents(Loc);
  335. TypeLoc ParentTypeLoc;
  336. if (!Parents.empty()) {
  337. // Handle cases of nested name specificier locations.
  338. //
  339. // The VisitNestedNameSpecifierLoc interface is not impelmented in
  340. // RecursiveASTVisitor, we have to handle it explicitly.
  341. if (const auto *NSL = Parents[0].get<NestedNameSpecifierLoc>()) {
  342. VisitNestedNameSpecifierLocations(*NSL);
  343. return true;
  344. }
  345. if (const auto *TL = Parents[0].get<TypeLoc>())
  346. ParentTypeLoc = *TL;
  347. }
  348. // Handle the outermost TypeLoc which is directly linked to the interesting
  349. // declaration and don't handle nested name specifier locations.
  350. if (const auto *TargetDecl = getSupportedDeclFromTypeLoc(Loc)) {
  351. if (isInUSRSet(TargetDecl)) {
  352. // Only handle the outermost typeLoc.
  353. //
  354. // For a type like "a::Foo", there will be two typeLocs for it.
  355. // One ElaboratedType, the other is RecordType:
  356. //
  357. // ElaboratedType 0x33b9390 'a::Foo' sugar
  358. // `-RecordType 0x338fef0 'class a::Foo'
  359. // `-CXXRecord 0x338fe58 'Foo'
  360. //
  361. // Skip if this is an inner typeLoc.
  362. if (!ParentTypeLoc.isNull() &&
  363. isInUSRSet(getSupportedDeclFromTypeLoc(ParentTypeLoc)))
  364. return true;
  365. auto StartLoc = StartLocationForType(Loc);
  366. auto EndLoc = EndLocationForType(Loc);
  367. if (IsValidEditLoc(Context.getSourceManager(), StartLoc)) {
  368. RenameInfo Info = {StartLoc,
  369. EndLoc,
  370. TargetDecl,
  371. getClosestAncestorDecl(Loc),
  372. GetNestedNameForType(Loc),
  373. /*IgnorePrefixQualifers=*/false};
  374. RenameInfos.push_back(Info);
  375. }
  376. return true;
  377. }
  378. }
  379. // Handle specific template class specialiation cases.
  380. if (const auto *TemplateSpecType =
  381. dyn_cast<TemplateSpecializationType>(Loc.getType())) {
  382. TypeLoc TargetLoc = Loc;
  383. if (!ParentTypeLoc.isNull()) {
  384. if (llvm::isa<ElaboratedType>(ParentTypeLoc.getType()))
  385. TargetLoc = ParentTypeLoc;
  386. }
  387. if (isInUSRSet(TemplateSpecType->getTemplateName().getAsTemplateDecl())) {
  388. TypeLoc TargetLoc = Loc;
  389. // FIXME: Find a better way to handle this case.
  390. // For the qualified template class specification type like
  391. // "ns::Foo<int>" in "ns::Foo<int>& f();", we want the parent typeLoc
  392. // (ElaboratedType) of the TemplateSpecializationType in order to
  393. // catch the prefix qualifiers "ns::".
  394. if (!ParentTypeLoc.isNull() &&
  395. llvm::isa<ElaboratedType>(ParentTypeLoc.getType()))
  396. TargetLoc = ParentTypeLoc;
  397. auto StartLoc = StartLocationForType(TargetLoc);
  398. auto EndLoc = EndLocationForType(TargetLoc);
  399. if (IsValidEditLoc(Context.getSourceManager(), StartLoc)) {
  400. RenameInfo Info = {
  401. StartLoc,
  402. EndLoc,
  403. TemplateSpecType->getTemplateName().getAsTemplateDecl(),
  404. getClosestAncestorDecl(DynTypedNode::create(TargetLoc)),
  405. GetNestedNameForType(TargetLoc),
  406. /*IgnorePrefixQualifers=*/false};
  407. RenameInfos.push_back(Info);
  408. }
  409. }
  410. }
  411. return true;
  412. }
  413. // Returns a list of RenameInfo.
  414. const std::vector<RenameInfo> &getRenameInfos() const { return RenameInfos; }
  415. // Returns a list of using declarations which are needed to update.
  416. const std::vector<const UsingDecl *> &getUsingDecls() const {
  417. return UsingDecls;
  418. }
  419. private:
  420. // Get the supported declaration from a given typeLoc. If the declaration type
  421. // is not supported, returns nullptr.
  422. const NamedDecl *getSupportedDeclFromTypeLoc(TypeLoc Loc) {
  423. if (const auto* TT = Loc.getType()->getAs<clang::TypedefType>())
  424. return TT->getDecl();
  425. if (const auto *RD = Loc.getType()->getAsCXXRecordDecl())
  426. return RD;
  427. if (const auto *ED =
  428. llvm::dyn_cast_or_null<EnumDecl>(Loc.getType()->getAsTagDecl()))
  429. return ED;
  430. return nullptr;
  431. }
  432. // Get the closest ancester which is a declaration of a given AST node.
  433. template <typename ASTNodeType>
  434. const Decl *getClosestAncestorDecl(const ASTNodeType &Node) {
  435. auto Parents = Context.getParents(Node);
  436. // FIXME: figure out how to handle it when there are multiple parents.
  437. if (Parents.size() != 1)
  438. return nullptr;
  439. if (ASTNodeKind::getFromNodeKind<Decl>().isBaseOf(Parents[0].getNodeKind()))
  440. return Parents[0].template get<Decl>();
  441. return getClosestAncestorDecl(Parents[0]);
  442. }
  443. // Get the parent typeLoc of a given typeLoc. If there is no such parent,
  444. // return nullptr.
  445. const TypeLoc *getParentTypeLoc(TypeLoc Loc) const {
  446. auto Parents = Context.getParents(Loc);
  447. // FIXME: figure out how to handle it when there are multiple parents.
  448. if (Parents.size() != 1)
  449. return nullptr;
  450. return Parents[0].get<TypeLoc>();
  451. }
  452. // Check whether the USR of a given Decl is in the USRSet.
  453. bool isInUSRSet(const Decl *Decl) const {
  454. auto USR = getUSRForDecl(Decl);
  455. if (USR.empty())
  456. return false;
  457. return llvm::is_contained(USRSet, USR);
  458. }
  459. const std::set<std::string> USRSet;
  460. ASTContext &Context;
  461. std::vector<RenameInfo> RenameInfos;
  462. // Record all interested using declarations which contains the using-shadow
  463. // declarations of the symbol declarations being renamed.
  464. std::vector<const UsingDecl *> UsingDecls;
  465. };
  466. } // namespace
  467. SymbolOccurrences getOccurrencesOfUSRs(ArrayRef<std::string> USRs,
  468. StringRef PrevName, Decl *Decl) {
  469. USRLocFindingASTVisitor Visitor(USRs, PrevName, Decl->getASTContext());
  470. Visitor.TraverseDecl(Decl);
  471. return Visitor.takeOccurrences();
  472. }
  473. std::vector<tooling::AtomicChange>
  474. createRenameAtomicChanges(llvm::ArrayRef<std::string> USRs,
  475. llvm::StringRef NewName, Decl *TranslationUnitDecl) {
  476. RenameLocFinder Finder(USRs, TranslationUnitDecl->getASTContext());
  477. Finder.TraverseDecl(TranslationUnitDecl);
  478. const SourceManager &SM =
  479. TranslationUnitDecl->getASTContext().getSourceManager();
  480. std::vector<tooling::AtomicChange> AtomicChanges;
  481. auto Replace = [&](SourceLocation Start, SourceLocation End,
  482. llvm::StringRef Text) {
  483. tooling::AtomicChange ReplaceChange = tooling::AtomicChange(SM, Start);
  484. llvm::Error Err = ReplaceChange.replace(
  485. SM, CharSourceRange::getTokenRange(Start, End), Text);
  486. if (Err) {
  487. llvm::errs() << "Failed to add replacement to AtomicChange: "
  488. << llvm::toString(std::move(Err)) << "\n";
  489. return;
  490. }
  491. AtomicChanges.push_back(std::move(ReplaceChange));
  492. };
  493. for (const auto &RenameInfo : Finder.getRenameInfos()) {
  494. std::string ReplacedName = NewName.str();
  495. if (RenameInfo.IgnorePrefixQualifers) {
  496. // Get the name without prefix qualifiers from NewName.
  497. size_t LastColonPos = NewName.find_last_of(':');
  498. if (LastColonPos != std::string::npos)
  499. ReplacedName = std::string(NewName.substr(LastColonPos + 1));
  500. } else {
  501. if (RenameInfo.FromDecl && RenameInfo.Context) {
  502. if (!llvm::isa<clang::TranslationUnitDecl>(
  503. RenameInfo.Context->getDeclContext())) {
  504. ReplacedName = tooling::replaceNestedName(
  505. RenameInfo.Specifier, RenameInfo.Begin,
  506. RenameInfo.Context->getDeclContext(), RenameInfo.FromDecl,
  507. NewName.startswith("::") ? NewName.str()
  508. : ("::" + NewName).str());
  509. } else {
  510. // This fixes the case where type `T` is a parameter inside a function
  511. // type (e.g. `std::function<void(T)>`) and the DeclContext of `T`
  512. // becomes the translation unit. As a workaround, we simply use
  513. // fully-qualified name here for all references whose `DeclContext` is
  514. // the translation unit and ignore the possible existence of
  515. // using-decls (in the global scope) that can shorten the replaced
  516. // name.
  517. llvm::StringRef ActualName = Lexer::getSourceText(
  518. CharSourceRange::getTokenRange(
  519. SourceRange(RenameInfo.Begin, RenameInfo.End)),
  520. SM, TranslationUnitDecl->getASTContext().getLangOpts());
  521. // Add the leading "::" back if the name written in the code contains
  522. // it.
  523. if (ActualName.startswith("::") && !NewName.startswith("::")) {
  524. ReplacedName = "::" + NewName.str();
  525. }
  526. }
  527. }
  528. // If the NewName contains leading "::", add it back.
  529. if (NewName.startswith("::") && NewName.substr(2) == ReplacedName)
  530. ReplacedName = NewName.str();
  531. }
  532. Replace(RenameInfo.Begin, RenameInfo.End, ReplacedName);
  533. }
  534. // Hanlde using declarations explicitly as "using a::Foo" don't trigger
  535. // typeLoc for "a::Foo".
  536. for (const auto *Using : Finder.getUsingDecls())
  537. Replace(Using->getBeginLoc(), Using->getEndLoc(), "using " + NewName.str());
  538. return AtomicChanges;
  539. }
  540. } // end namespace tooling
  541. } // end namespace clang