USRLocFinder.cpp revision 353358
133965Sjdp//===--- USRLocFinder.cpp - Clang refactoring library ---------------------===//
278828Sobrien//
3218822Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
433965Sjdp// See https://llvm.org/LICENSE.txt for license information.
533965Sjdp// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
633965Sjdp//
7130561Sobrien//===----------------------------------------------------------------------===//
833965Sjdp///
9130561Sobrien/// \file
10130561Sobrien/// Methods for finding all instances of a USR. Our strategy is very
11130561Sobrien/// simple; we just compare the USR at every relevant AST node with the one
12130561Sobrien/// provided.
1333965Sjdp///
14130561Sobrien//===----------------------------------------------------------------------===//
15130561Sobrien
16130561Sobrien#include "clang/Tooling/Refactoring/Rename/USRLocFinder.h"
17130561Sobrien#include "clang/AST/ASTContext.h"
1833965Sjdp#include "clang/AST/RecursiveASTVisitor.h"
19130561Sobrien#include "clang/Basic/LLVM.h"
20130561Sobrien#include "clang/Basic/SourceLocation.h"
21218822Sdim#include "clang/Basic/SourceManager.h"
2233965Sjdp#include "clang/Lex/Lexer.h"
2333965Sjdp#include "clang/Tooling/Core/Lookup.h"
2433965Sjdp#include "clang/Tooling/Refactoring/RecursiveSymbolVisitor.h"
2533965Sjdp#include "clang/Tooling/Refactoring/Rename/SymbolName.h"
2633965Sjdp#include "clang/Tooling/Refactoring/Rename/USRFinder.h"
2733965Sjdp#include "llvm/ADT/StringRef.h"
2833965Sjdp#include "llvm/Support/Casting.h"
2960484Sobrien#include <cstddef>
3033965Sjdp#include <set>
3133965Sjdp#include <string>
3233965Sjdp#include <vector>
3333965Sjdp
3433965Sjdpusing namespace llvm;
3533965Sjdp
3633965Sjdpnamespace clang {
3733965Sjdpnamespace tooling {
3833965Sjdp
3933965Sjdpnamespace {
4033965Sjdp
4133965Sjdp// Returns true if the given Loc is valid for edit. We don't edit the
4233965Sjdp// SourceLocations that are valid or in temporary buffer.
4333965Sjdpbool IsValidEditLoc(const clang::SourceManager& SM, clang::SourceLocation Loc) {
4433965Sjdp  if (Loc.isInvalid())
4533965Sjdp    return false;
4633965Sjdp  const clang::FullSourceLoc FullLoc(Loc, SM);
4733965Sjdp  std::pair<clang::FileID, unsigned> FileIdAndOffset =
4833965Sjdp      FullLoc.getSpellingLoc().getDecomposedLoc();
4933965Sjdp  return SM.getFileEntryForID(FileIdAndOffset.first) != nullptr;
50218822Sdim}
5133965Sjdp
5233965Sjdp// This visitor recursively searches for all instances of a USR in a
5333965Sjdp// translation unit and stores them for later usage.
5433965Sjdpclass USRLocFindingASTVisitor
5533965Sjdp    : public RecursiveSymbolVisitor<USRLocFindingASTVisitor> {
5633965Sjdppublic:
5733965Sjdp  explicit USRLocFindingASTVisitor(const std::vector<std::string> &USRs,
5833965Sjdp                                   StringRef PrevName,
5933965Sjdp                                   const ASTContext &Context)
6033965Sjdp      : RecursiveSymbolVisitor(Context.getSourceManager(),
6133965Sjdp                               Context.getLangOpts()),
6233965Sjdp        USRSet(USRs.begin(), USRs.end()), PrevName(PrevName), Context(Context) {
6333965Sjdp  }
6433965Sjdp
6533965Sjdp  bool visitSymbolOccurrence(const NamedDecl *ND,
6633965Sjdp                             ArrayRef<SourceRange> NameRanges) {
6733965Sjdp    if (USRSet.find(getUSRForDecl(ND)) != USRSet.end()) {
6891041Sobrien      assert(NameRanges.size() == 1 &&
6933965Sjdp             "Multiple name pieces are not supported yet!");
7033965Sjdp      SourceLocation Loc = NameRanges[0].getBegin();
7191041Sobrien      const SourceManager &SM = Context.getSourceManager();
7233965Sjdp      // TODO: Deal with macro occurrences correctly.
7333965Sjdp      if (Loc.isMacroID())
7491041Sobrien        Loc = SM.getSpellingLoc(Loc);
7533965Sjdp      checkAndAddLocation(Loc);
7633965Sjdp    }
7791041Sobrien    return true;
7833965Sjdp  }
7933965Sjdp
8091041Sobrien  // Non-visitors:
8133965Sjdp
8233965Sjdp  /// Returns a set of unique symbol occurrences. Duplicate or
8391041Sobrien  /// overlapping occurrences are erroneous and should be reported!
8433965Sjdp  SymbolOccurrences takeOccurrences() { return std::move(Occurrences); }
8533965Sjdp
8691041Sobrienprivate:
8733965Sjdp  void checkAndAddLocation(SourceLocation Loc) {
8833965Sjdp    const SourceLocation BeginLoc = Loc;
8989857Sobrien    const SourceLocation EndLoc = Lexer::getLocForEndOfToken(
9089857Sobrien        BeginLoc, 0, Context.getSourceManager(), Context.getLangOpts());
9189857Sobrien    StringRef TokenName =
9289857Sobrien        Lexer::getSourceText(CharSourceRange::getTokenRange(BeginLoc, EndLoc),
9333965Sjdp                             Context.getSourceManager(), Context.getLangOpts());
9433965Sjdp    size_t Offset = TokenName.find(PrevName.getNamePieces()[0]);
9533965Sjdp
9633965Sjdp    // The token of the source location we find actually has the old
9733965Sjdp    // name.
9833965Sjdp    if (Offset != StringRef::npos)
9933965Sjdp      Occurrences.emplace_back(PrevName, SymbolOccurrence::MatchingSymbol,
10091041Sobrien                               BeginLoc.getLocWithOffset(Offset));
101130561Sobrien  }
10233965Sjdp
10391041Sobrien  const std::set<std::string> USRSet;
10433965Sjdp  const SymbolName PrevName;
10533965Sjdp  SymbolOccurrences Occurrences;
10691041Sobrien  const ASTContext &Context;
10733965Sjdp};
10833965Sjdp
10991041SobrienSourceLocation StartLocationForType(TypeLoc TL) {
11033965Sjdp  // For elaborated types (e.g. `struct a::A`) we want the portion after the
11133965Sjdp  // `struct` but including the namespace qualifier, `a::`.
11291041Sobrien  if (auto ElaboratedTypeLoc = TL.getAs<clang::ElaboratedTypeLoc>()) {
11391041Sobrien    NestedNameSpecifierLoc NestedNameSpecifier =
11491041Sobrien        ElaboratedTypeLoc.getQualifierLoc();
11533965Sjdp    if (NestedNameSpecifier.getNestedNameSpecifier())
11633965Sjdp      return NestedNameSpecifier.getBeginLoc();
11733965Sjdp    TL = TL.getNextTypeLoc();
11833965Sjdp  }
11933965Sjdp  return TL.getBeginLoc();
12033965Sjdp}
12133965Sjdp
12233965SjdpSourceLocation EndLocationForType(TypeLoc TL) {
12333965Sjdp  // Dig past any namespace or keyword qualifications.
12433965Sjdp  while (TL.getTypeLocClass() == TypeLoc::Elaborated ||
125130561Sobrien         TL.getTypeLocClass() == TypeLoc::Qualified)
126130561Sobrien    TL = TL.getNextTypeLoc();
127130561Sobrien
128130561Sobrien  // The location for template specializations (e.g. Foo<int>) includes the
129130561Sobrien  // templated types in its location range.  We want to restrict this to just
130130561Sobrien  // before the `<` character.
131130561Sobrien  if (TL.getTypeLocClass() == TypeLoc::TemplateSpecialization) {
132130561Sobrien    return TL.castAs<TemplateSpecializationTypeLoc>()
133130561Sobrien        .getLAngleLoc()
134130561Sobrien        .getLocWithOffset(-1);
13533965Sjdp  }
13633965Sjdp  return TL.getEndLoc();
13733965Sjdp}
13833965Sjdp
13933965SjdpNestedNameSpecifier *GetNestedNameForType(TypeLoc TL) {
14033965Sjdp  // Dig past any keyword qualifications.
14133965Sjdp  while (TL.getTypeLocClass() == TypeLoc::Qualified)
14233965Sjdp    TL = TL.getNextTypeLoc();
14333965Sjdp
14433965Sjdp  // For elaborated types (e.g. `struct a::A`) we want the portion after the
14533965Sjdp  // `struct` but including the namespace qualifier, `a::`.
14633965Sjdp  if (auto ElaboratedTypeLoc = TL.getAs<clang::ElaboratedTypeLoc>())
14733965Sjdp    return ElaboratedTypeLoc.getQualifierLoc().getNestedNameSpecifier();
14833965Sjdp  return nullptr;
14933965Sjdp}
15033965Sjdp
15133965Sjdp// Find all locations identified by the given USRs for rename.
15233965Sjdp//
15333965Sjdp// This class will traverse the AST and find every AST node whose USR is in the
15433965Sjdp// given USRs' set.
15533965Sjdpclass RenameLocFinder : public RecursiveASTVisitor<RenameLocFinder> {
15633965Sjdppublic:
15733965Sjdp  RenameLocFinder(llvm::ArrayRef<std::string> USRs, ASTContext &Context)
15833965Sjdp      : USRSet(USRs.begin(), USRs.end()), Context(Context) {}
15933965Sjdp
16033965Sjdp  // A structure records all information of a symbol reference being renamed.
16133965Sjdp  // We try to add as few prefix qualifiers as possible.
16233965Sjdp  struct RenameInfo {
16333965Sjdp    // The begin location of a symbol being renamed.
16433965Sjdp    SourceLocation Begin;
16533965Sjdp    // The end location of a symbol being renamed.
16633965Sjdp    SourceLocation End;
16733965Sjdp    // The declaration of a symbol being renamed (can be nullptr).
16833965Sjdp    const NamedDecl *FromDecl;
16933965Sjdp    // The declaration in which the nested name is contained (can be nullptr).
17033965Sjdp    const Decl *Context;
17133965Sjdp    // The nested name being replaced (can be nullptr).
17233965Sjdp    const NestedNameSpecifier *Specifier;
17333965Sjdp    // Determine whether the prefix qualifiers of the NewName should be ignored.
17433965Sjdp    // Normally, we set it to true for the symbol declaration and definition to
17533965Sjdp    // avoid adding prefix qualifiers.
17633965Sjdp    // For example, if it is true and NewName is "a::b::foo", then the symbol
17733965Sjdp    // occurrence which the RenameInfo points to will be renamed to "foo".
17833965Sjdp    bool IgnorePrefixQualifers;
17933965Sjdp  };
18033965Sjdp
18133965Sjdp  bool VisitNamedDecl(const NamedDecl *Decl) {
18233965Sjdp    // UsingDecl has been handled in other place.
18333965Sjdp    if (llvm::isa<UsingDecl>(Decl))
18433965Sjdp      return true;
18533965Sjdp
18633965Sjdp    // DestructorDecl has been handled in Typeloc.
18733965Sjdp    if (llvm::isa<CXXDestructorDecl>(Decl))
18833965Sjdp      return true;
18933965Sjdp
19033965Sjdp    if (Decl->isImplicit())
19133965Sjdp      return true;
19233965Sjdp
19333965Sjdp    if (isInUSRSet(Decl)) {
19433965Sjdp      // For the case of renaming an alias template, we actually rename the
19533965Sjdp      // underlying alias declaration of the template.
19633965Sjdp      if (const auto* TAT = dyn_cast<TypeAliasTemplateDecl>(Decl))
19733965Sjdp        Decl = TAT->getTemplatedDecl();
19833965Sjdp
19933965Sjdp      auto StartLoc = Decl->getLocation();
20033965Sjdp      auto EndLoc = StartLoc;
20133965Sjdp      if (IsValidEditLoc(Context.getSourceManager(), StartLoc)) {
20233965Sjdp        RenameInfo Info = {StartLoc,
20333965Sjdp                           EndLoc,
20433965Sjdp                           /*FromDecl=*/nullptr,
20533965Sjdp                           /*Context=*/nullptr,
20633965Sjdp                           /*Specifier=*/nullptr,
20733965Sjdp                           /*IgnorePrefixQualifers=*/true};
20833965Sjdp        RenameInfos.push_back(Info);
20933965Sjdp      }
21033965Sjdp    }
21133965Sjdp    return true;
21233965Sjdp  }
21333965Sjdp
21433965Sjdp  bool VisitMemberExpr(const MemberExpr *Expr) {
21533965Sjdp    const NamedDecl *Decl = Expr->getFoundDecl();
21633965Sjdp    auto StartLoc = Expr->getMemberLoc();
21733965Sjdp    auto EndLoc = Expr->getMemberLoc();
21833965Sjdp    if (isInUSRSet(Decl)) {
21933965Sjdp      RenameInfos.push_back({StartLoc, EndLoc,
22033965Sjdp                            /*FromDecl=*/nullptr,
22133965Sjdp                            /*Context=*/nullptr,
22233965Sjdp                            /*Specifier=*/nullptr,
22333965Sjdp                            /*IgnorePrefixQualifiers=*/true});
22433965Sjdp    }
22533965Sjdp    return true;
22633965Sjdp  }
22733965Sjdp
22833965Sjdp  bool VisitCXXConstructorDecl(const CXXConstructorDecl *CD) {
22933965Sjdp    // Fix the constructor initializer when renaming class members.
23033965Sjdp    for (const auto *Initializer : CD->inits()) {
23133965Sjdp      // Ignore implicit initializers.
23233965Sjdp      if (!Initializer->isWritten())
23333965Sjdp        continue;
23433965Sjdp
23533965Sjdp      if (const FieldDecl *FD = Initializer->getMember()) {
23633965Sjdp        if (isInUSRSet(FD)) {
23733965Sjdp          auto Loc = Initializer->getSourceLocation();
23833965Sjdp          RenameInfos.push_back({Loc, Loc,
23933965Sjdp                                 /*FromDecl=*/nullptr,
24033965Sjdp                                 /*Context=*/nullptr,
24133965Sjdp                                 /*Specifier=*/nullptr,
24233965Sjdp                                 /*IgnorePrefixQualifiers=*/true});
24333965Sjdp        }
24433965Sjdp      }
24533965Sjdp    }
24633965Sjdp    return true;
24733965Sjdp  }
24833965Sjdp
24933965Sjdp  bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
25033965Sjdp    const NamedDecl *Decl = Expr->getFoundDecl();
25133965Sjdp    // Get the underlying declaration of the shadow declaration introduced by a
25233965Sjdp    // using declaration.
25333965Sjdp    if (auto *UsingShadow = llvm::dyn_cast<UsingShadowDecl>(Decl)) {
25433965Sjdp      Decl = UsingShadow->getTargetDecl();
25591041Sobrien    }
25633965Sjdp
25733965Sjdp    auto StartLoc = Expr->getBeginLoc();
258218822Sdim    // For template function call expressions like `foo<int>()`, we want to
259218822Sdim    // restrict the end of location to just before the `<` character.
260218822Sdim    SourceLocation EndLoc = Expr->hasExplicitTemplateArgs()
26133965Sjdp                                ? Expr->getLAngleLoc().getLocWithOffset(-1)
26233965Sjdp                                : Expr->getEndLoc();
263218822Sdim
26491041Sobrien    if (const auto *MD = llvm::dyn_cast<CXXMethodDecl>(Decl)) {
26533965Sjdp      if (isInUSRSet(MD)) {
26633965Sjdp        // Handle renaming static template class methods, we only rename the
26789857Sobrien        // name without prefix qualifiers and restrict the source range to the
26891041Sobrien        // name.
26933965Sjdp        RenameInfos.push_back({EndLoc, EndLoc,
27033965Sjdp                               /*FromDecl=*/nullptr,
27133965Sjdp                               /*Context=*/nullptr,
27233965Sjdp                               /*Specifier=*/nullptr,
27333965Sjdp                               /*IgnorePrefixQualifiers=*/true});
27433965Sjdp        return true;
27533965Sjdp      }
27633965Sjdp    }
27733965Sjdp
27833965Sjdp    // In case of renaming an enum declaration, we have to explicitly handle
27933965Sjdp    // unscoped enum constants referenced in expressions (e.g.
28033965Sjdp    // "auto r = ns1::ns2::Green" where Green is an enum constant of an unscoped
28133965Sjdp    // enum decl "ns1::ns2::Color") as these enum constants cannot be caught by
282130561Sobrien    // TypeLoc.
28333965Sjdp    if (const auto *T = llvm::dyn_cast<EnumConstantDecl>(Decl)) {
28433965Sjdp      // FIXME: Handle the enum constant without prefix qualifiers (`a = Green`)
28533965Sjdp      // when renaming an unscoped enum declaration with a new namespace.
28689857Sobrien      if (!Expr->hasQualifier())
28789857Sobrien        return true;
28889857Sobrien
28989857Sobrien      if (const auto *ED =
29089857Sobrien              llvm::dyn_cast_or_null<EnumDecl>(getClosestAncestorDecl(*T))) {
29189857Sobrien        if (ED->isScoped())
29233965Sjdp          return true;
29333965Sjdp        Decl = ED;
29489857Sobrien      }
29589857Sobrien      // The current fix would qualify "ns1::ns2::Green" as
29633965Sjdp      // "ns1::ns2::Color::Green".
29733965Sjdp      //
29889857Sobrien      // Get the EndLoc of the replacement by moving 1 character backward (
29989857Sobrien      // to exclude the last '::').
30089857Sobrien      //
30133965Sjdp      //    ns1::ns2::Green;
30233965Sjdp      //    ^      ^^
30389857Sobrien      // BeginLoc  |EndLoc of the qualifier
30489857Sobrien      //           new EndLoc
30533965Sjdp      EndLoc = Expr->getQualifierLoc().getEndLoc().getLocWithOffset(-1);
30633965Sjdp      assert(EndLoc.isValid() &&
30789857Sobrien             "The enum constant should have prefix qualifers.");
30889857Sobrien    }
30989857Sobrien    if (isInUSRSet(Decl) &&
31089857Sobrien        IsValidEditLoc(Context.getSourceManager(), StartLoc)) {
311130561Sobrien      RenameInfo Info = {StartLoc,
31233965Sjdp                         EndLoc,
31389857Sobrien                         Decl,
31489857Sobrien                         getClosestAncestorDecl(*Expr),
31533965Sjdp                         Expr->getQualifier(),
31633965Sjdp                         /*IgnorePrefixQualifers=*/false};
31789857Sobrien      RenameInfos.push_back(Info);
31889857Sobrien    }
31933965Sjdp
32033965Sjdp    return true;
32189857Sobrien  }
32289857Sobrien
323130561Sobrien  bool VisitUsingDecl(const UsingDecl *Using) {
32489857Sobrien    for (const auto *UsingShadow : Using->shadows()) {
32533965Sjdp      if (isInUSRSet(UsingShadow->getTargetDecl())) {
326130561Sobrien        UsingDecls.push_back(Using);
327130561Sobrien        break;
32833965Sjdp      }
32989857Sobrien    }
33033965Sjdp    return true;
33133965Sjdp  }
33289857Sobrien
33389857Sobrien  bool VisitNestedNameSpecifierLocations(NestedNameSpecifierLoc NestedLoc) {
33489857Sobrien    if (!NestedLoc.getNestedNameSpecifier()->getAsType())
33589857Sobrien      return true;
33689857Sobrien
33789857Sobrien    if (const auto *TargetDecl =
33889857Sobrien            getSupportedDeclFromTypeLoc(NestedLoc.getTypeLoc())) {
33989857Sobrien      if (isInUSRSet(TargetDecl)) {
34089857Sobrien        RenameInfo Info = {NestedLoc.getBeginLoc(),
34189857Sobrien                           EndLocationForType(NestedLoc.getTypeLoc()),
34289857Sobrien                           TargetDecl,
34389857Sobrien                           getClosestAncestorDecl(NestedLoc),
34489857Sobrien                           NestedLoc.getNestedNameSpecifier()->getPrefix(),
34589857Sobrien                           /*IgnorePrefixQualifers=*/false};
34689857Sobrien        RenameInfos.push_back(Info);
347130561Sobrien      }
34833965Sjdp    }
349130561Sobrien    return true;
350130561Sobrien  }
351130561Sobrien
352130561Sobrien  bool VisitTypeLoc(TypeLoc Loc) {
353130561Sobrien    auto Parents = Context.getParents(Loc);
354130561Sobrien    TypeLoc ParentTypeLoc;
355130561Sobrien    if (!Parents.empty()) {
356130561Sobrien      // Handle cases of nested name specificier locations.
35733965Sjdp      //
35833965Sjdp      // The VisitNestedNameSpecifierLoc interface is not impelmented in
359130561Sobrien      // RecursiveASTVisitor, we have to handle it explicitly.
360130561Sobrien      if (const auto *NSL = Parents[0].get<NestedNameSpecifierLoc>()) {
36133965Sjdp        VisitNestedNameSpecifierLocations(*NSL);
36233965Sjdp        return true;
36389857Sobrien      }
36489857Sobrien
36589857Sobrien      if (const auto *TL = Parents[0].get<TypeLoc>())
36689857Sobrien        ParentTypeLoc = *TL;
36789857Sobrien    }
36889857Sobrien
369130561Sobrien    // Handle the outermost TypeLoc which is directly linked to the interesting
37033965Sjdp    // declaration and don't handle nested name specifier locations.
37191041Sobrien    if (const auto *TargetDecl = getSupportedDeclFromTypeLoc(Loc)) {
37233965Sjdp      if (isInUSRSet(TargetDecl)) {
37333965Sjdp        // Only handle the outermost typeLoc.
37433965Sjdp        //
37533965Sjdp        // For a type like "a::Foo", there will be two typeLocs for it.
37633965Sjdp        // One ElaboratedType, the other is RecordType:
37733965Sjdp        //
37833965Sjdp        //   ElaboratedType 0x33b9390 'a::Foo' sugar
37933965Sjdp        //   `-RecordType 0x338fef0 'class a::Foo'
38033965Sjdp        //     `-CXXRecord 0x338fe58 'Foo'
38189857Sobrien        //
38289857Sobrien        // Skip if this is an inner typeLoc.
38333965Sjdp        if (!ParentTypeLoc.isNull() &&
38433965Sjdp            isInUSRSet(getSupportedDeclFromTypeLoc(ParentTypeLoc)))
38533965Sjdp          return true;
38633965Sjdp
38733965Sjdp        auto StartLoc = StartLocationForType(Loc);
38889857Sobrien        auto EndLoc = EndLocationForType(Loc);
38989857Sobrien        if (IsValidEditLoc(Context.getSourceManager(), StartLoc)) {
390130561Sobrien          RenameInfo Info = {StartLoc,
39133965Sjdp                             EndLoc,
39260484Sobrien                             TargetDecl,
39333965Sjdp                             getClosestAncestorDecl(Loc),
39460484Sobrien                             GetNestedNameForType(Loc),
39560484Sobrien                             /*IgnorePrefixQualifers=*/false};
39660484Sobrien          RenameInfos.push_back(Info);
397130561Sobrien        }
398130561Sobrien        return true;
39960484Sobrien      }
40060484Sobrien    }
40160484Sobrien
40233965Sjdp    // Handle specific template class specialiation cases.
40333965Sjdp    if (const auto *TemplateSpecType =
40489857Sobrien            dyn_cast<TemplateSpecializationType>(Loc.getType())) {
40589857Sobrien      TypeLoc TargetLoc = Loc;
406130561Sobrien      if (!ParentTypeLoc.isNull()) {
40789857Sobrien        if (llvm::isa<ElaboratedType>(ParentTypeLoc.getType()))
40889857Sobrien          TargetLoc = ParentTypeLoc;
40989857Sobrien      }
41089857Sobrien
41189857Sobrien      if (isInUSRSet(TemplateSpecType->getTemplateName().getAsTemplateDecl())) {
41289857Sobrien        TypeLoc TargetLoc = Loc;
41389857Sobrien        // FIXME: Find a better way to handle this case.
41489857Sobrien        // For the qualified template class specification type like
41589857Sobrien        // "ns::Foo<int>" in "ns::Foo<int>& f();", we want the parent typeLoc
41689857Sobrien        // (ElaboratedType) of the TemplateSpecializationType in order to
41789857Sobrien        // catch the prefix qualifiers "ns::".
41891041Sobrien        if (!ParentTypeLoc.isNull() &&
41933965Sjdp            llvm::isa<ElaboratedType>(ParentTypeLoc.getType()))
42033965Sjdp          TargetLoc = ParentTypeLoc;
42133965Sjdp
42233965Sjdp        auto StartLoc = StartLocationForType(TargetLoc);
42333965Sjdp        auto EndLoc = EndLocationForType(TargetLoc);
42433965Sjdp        if (IsValidEditLoc(Context.getSourceManager(), StartLoc)) {
42533965Sjdp          RenameInfo Info = {
42638889Sjdp              StartLoc,
42733965Sjdp              EndLoc,
42833965Sjdp              TemplateSpecType->getTemplateName().getAsTemplateDecl(),
42933965Sjdp              getClosestAncestorDecl(
43033965Sjdp                  ast_type_traits::DynTypedNode::create(TargetLoc)),
43133965Sjdp              GetNestedNameForType(TargetLoc),
43233965Sjdp              /*IgnorePrefixQualifers=*/false};
43338889Sjdp          RenameInfos.push_back(Info);
434130561Sobrien        }
43533965Sjdp      }
43633965Sjdp    }
43733965Sjdp    return true;
43833965Sjdp  }
43933965Sjdp
44033965Sjdp  // Returns a list of RenameInfo.
44133965Sjdp  const std::vector<RenameInfo> &getRenameInfos() const { return RenameInfos; }
44233965Sjdp
44333965Sjdp  // Returns a list of using declarations which are needed to update.
44433965Sjdp  const std::vector<const UsingDecl *> &getUsingDecls() const {
44533965Sjdp    return UsingDecls;
44633965Sjdp  }
44733965Sjdp
44833965Sjdpprivate:
44933965Sjdp  // Get the supported declaration from a given typeLoc. If the declaration type
45033965Sjdp  // is not supported, returns nullptr.
45133965Sjdp  const NamedDecl *getSupportedDeclFromTypeLoc(TypeLoc Loc) {
45233965Sjdp    if (const auto* TT = Loc.getType()->getAs<clang::TypedefType>())
45333965Sjdp      return TT->getDecl();
45433965Sjdp    if (const auto *RD = Loc.getType()->getAsCXXRecordDecl())
45533965Sjdp      return RD;
45633965Sjdp    if (const auto *ED =
45789857Sobrien            llvm::dyn_cast_or_null<EnumDecl>(Loc.getType()->getAsTagDecl()))
45889857Sobrien      return ED;
45933965Sjdp    return nullptr;
46089857Sobrien  }
46191041Sobrien
46291041Sobrien  // Get the closest ancester which is a declaration of a given AST node.
46391041Sobrien  template <typename ASTNodeType>
46433965Sjdp  const Decl *getClosestAncestorDecl(const ASTNodeType &Node) {
46533965Sjdp    auto Parents = Context.getParents(Node);
46660484Sobrien    // FIXME: figure out how to handle it when there are multiple parents.
46760484Sobrien    if (Parents.size() != 1)
46833965Sjdp      return nullptr;
46938889Sjdp    if (ast_type_traits::ASTNodeKind::getFromNodeKind<Decl>().isBaseOf(
47038889Sjdp            Parents[0].getNodeKind()))
47138889Sjdp      return Parents[0].template get<Decl>();
47233965Sjdp    return getClosestAncestorDecl(Parents[0]);
47338889Sjdp  }
474130561Sobrien
475130561Sobrien  // Get the parent typeLoc of a given typeLoc. If there is no such parent,
476130561Sobrien  // return nullptr.
477130561Sobrien  const TypeLoc *getParentTypeLoc(TypeLoc Loc) const {
478130561Sobrien    auto Parents = Context.getParents(Loc);
479130561Sobrien    // FIXME: figure out how to handle it when there are multiple parents.
48038889Sjdp    if (Parents.size() != 1)
48138889Sjdp      return nullptr;
48260484Sobrien    return Parents[0].get<TypeLoc>();
48360484Sobrien  }
48460484Sobrien
48560484Sobrien  // Check whether the USR of a given Decl is in the USRSet.
48660484Sobrien  bool isInUSRSet(const Decl *Decl) const {
48738889Sjdp    auto USR = getUSRForDecl(Decl);
48838889Sjdp    if (USR.empty())
48938889Sjdp      return false;
49038889Sjdp    return llvm::is_contained(USRSet, USR);
491130561Sobrien  }
492130561Sobrien
493130561Sobrien  const std::set<std::string> USRSet;
494130561Sobrien  ASTContext &Context;
495130561Sobrien  std::vector<RenameInfo> RenameInfos;
49638889Sjdp  // Record all interested using declarations which contains the using-shadow
49760484Sobrien  // declarations of the symbol declarations being renamed.
49838889Sjdp  std::vector<const UsingDecl *> UsingDecls;
49938889Sjdp};
50060484Sobrien
50160484Sobrien} // namespace
50260484Sobrien
50360484SobrienSymbolOccurrences getOccurrencesOfUSRs(ArrayRef<std::string> USRs,
50460484Sobrien                                       StringRef PrevName, Decl *Decl) {
505218822Sdim  USRLocFindingASTVisitor Visitor(USRs, PrevName, Decl->getASTContext());
50660484Sobrien  Visitor.TraverseDecl(Decl);
507218822Sdim  return Visitor.takeOccurrences();
50860484Sobrien}
50938889Sjdp
51038889Sjdpstd::vector<tooling::AtomicChange>
51138889SjdpcreateRenameAtomicChanges(llvm::ArrayRef<std::string> USRs,
51238889Sjdp                          llvm::StringRef NewName, Decl *TranslationUnitDecl) {
51338889Sjdp  RenameLocFinder Finder(USRs, TranslationUnitDecl->getASTContext());
51438889Sjdp  Finder.TraverseDecl(TranslationUnitDecl);
51560484Sobrien
51660484Sobrien  const SourceManager &SM =
51760484Sobrien      TranslationUnitDecl->getASTContext().getSourceManager();
518218822Sdim
519218822Sdim  std::vector<tooling::AtomicChange> AtomicChanges;
520218822Sdim  auto Replace = [&](SourceLocation Start, SourceLocation End,
521218822Sdim                     llvm::StringRef Text) {
522218822Sdim    tooling::AtomicChange ReplaceChange = tooling::AtomicChange(SM, Start);
523218822Sdim    llvm::Error Err = ReplaceChange.replace(
524218822Sdim        SM, CharSourceRange::getTokenRange(Start, End), Text);
525218822Sdim    if (Err) {
52660484Sobrien      llvm::errs() << "Failed to add replacement to AtomicChange: "
52760484Sobrien                   << llvm::toString(std::move(Err)) << "\n";
52860484Sobrien      return;
52938889Sjdp    }
53038889Sjdp    AtomicChanges.push_back(std::move(ReplaceChange));
53138889Sjdp  };
53260484Sobrien
533218822Sdim  for (const auto &RenameInfo : Finder.getRenameInfos()) {
53460484Sobrien    std::string ReplacedName = NewName.str();
53538889Sjdp    if (RenameInfo.IgnorePrefixQualifers) {
53638889Sjdp      // Get the name without prefix qualifiers from NewName.
53738889Sjdp      size_t LastColonPos = NewName.find_last_of(':');
53838889Sjdp      if (LastColonPos != std::string::npos)
53938889Sjdp        ReplacedName = NewName.substr(LastColonPos + 1);
54038889Sjdp    } else {
54138889Sjdp      if (RenameInfo.FromDecl && RenameInfo.Context) {
54238889Sjdp        if (!llvm::isa<clang::TranslationUnitDecl>(
54338889Sjdp                RenameInfo.Context->getDeclContext())) {
54433965Sjdp          ReplacedName = tooling::replaceNestedName(
54533965Sjdp              RenameInfo.Specifier, RenameInfo.Begin,
54633965Sjdp              RenameInfo.Context->getDeclContext(), RenameInfo.FromDecl,
54733965Sjdp              NewName.startswith("::") ? NewName.str()
54833965Sjdp                                       : ("::" + NewName).str());
549130561Sobrien        } else {
550130561Sobrien          // This fixes the case where type `T` is a parameter inside a function
551130561Sobrien          // type (e.g. `std::function<void(T)>`) and the DeclContext of `T`
552130561Sobrien          // becomes the translation unit. As a workaround, we simply use
553130561Sobrien          // fully-qualified name here for all references whose `DeclContext` is
554130561Sobrien          // the translation unit and ignore the possible existence of
555130561Sobrien          // using-decls (in the global scope) that can shorten the replaced
55633965Sjdp          // name.
55733965Sjdp          llvm::StringRef ActualName = Lexer::getSourceText(
55833965Sjdp              CharSourceRange::getTokenRange(
55933965Sjdp                  SourceRange(RenameInfo.Begin, RenameInfo.End)),
56033965Sjdp              SM, TranslationUnitDecl->getASTContext().getLangOpts());
56133965Sjdp          // Add the leading "::" back if the name written in the code contains
56233965Sjdp          // it.
56333965Sjdp          if (ActualName.startswith("::") && !NewName.startswith("::")) {
56433965Sjdp            ReplacedName = "::" + NewName.str();
56533965Sjdp          }
56633965Sjdp        }
56733965Sjdp      }
56833965Sjdp      // If the NewName contains leading "::", add it back.
56933965Sjdp      if (NewName.startswith("::") && NewName.substr(2) == ReplacedName)
57033965Sjdp        ReplacedName = NewName.str();
57133965Sjdp    }
57233965Sjdp    Replace(RenameInfo.Begin, RenameInfo.End, ReplacedName);
57333965Sjdp  }
57433965Sjdp
57533965Sjdp  // Hanlde using declarations explicitly as "using a::Foo" don't trigger
576130561Sobrien  // typeLoc for "a::Foo".
577130561Sobrien  for (const auto *Using : Finder.getUsingDecls())
578130561Sobrien    Replace(Using->getBeginLoc(), Using->getEndLoc(), "using " + NewName.str());
579130561Sobrien
580130561Sobrien  return AtomicChanges;
581130561Sobrien}
58233965Sjdp
58333965Sjdp} // end namespace tooling
58433965Sjdp} // end namespace clang
58560484Sobrien