コード例 #1
0
// Get the USRs for the constructors of the class.
static std::vector<std::string> getAllConstructorUSRs(
    const CXXRecordDecl *Decl) {
  std::vector<std::string> USRs;

  // We need to get the definition of the record (as opposed to any forward
  // declarations) in order to find the constructor and destructor.
  const auto *RecordDecl = Decl->getDefinition();

  // Iterate over all the constructors and add their USRs.
  for (const auto *CtorDecl : RecordDecl->ctors())
    USRs.push_back(getUSRForDecl(CtorDecl));

  // Ignore destructors. GetLocationsOfUSR will find the declaration of and
  // explicit calls to a destructor through TagTypeLoc (and it is better for the
  // purpose of renaming).
  //
  // For example, in the following code segment,
  //  1  class C {
  //  2    ~C();
  //  3  };
  // At line 3, there is a NamedDecl starting from '~' and a TagTypeLoc starting
  // from 'C'.

  return USRs;
}
コード例 #2
0
static void populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D,
                                 const FullComment *FC, int LineNumber,
                                 StringRef Filename) {
  populateSymbolInfo(I, D, FC, LineNumber, Filename);
  if (const auto *T = getDeclForType(D->getReturnType())) {
    if (dyn_cast<EnumDecl>(T))
      I.ReturnType =
          TypeInfo(getUSRForDecl(T), T->getNameAsString(), InfoType::IT_enum);
    else if (dyn_cast<RecordDecl>(T))
      I.ReturnType =
          TypeInfo(getUSRForDecl(T), T->getNameAsString(), InfoType::IT_record);
  } else {
    I.ReturnType = TypeInfo(D->getReturnType().getAsString());
  }
  parseParameters(I, D);
}
コード例 #3
0
static void parseParameters(FunctionInfo &I, const FunctionDecl *D) {
  for (const ParmVarDecl *P : D->parameters()) {
    if (const auto *T = getDeclForType(P->getOriginalType())) {
      if (const auto *N = dyn_cast<EnumDecl>(T)) {
        I.Params.emplace_back(getUSRForDecl(N), N->getNameAsString(),
                              InfoType::IT_enum, P->getNameAsString());
        continue;
      } else if (const auto *N = dyn_cast<RecordDecl>(T)) {
        I.Params.emplace_back(getUSRForDecl(N), N->getNameAsString(),
                              InfoType::IT_record, P->getNameAsString());
        continue;
      }
    }
    I.Params.emplace_back(P->getOriginalType().getAsString(),
                          P->getNameAsString());
  }
}
コード例 #4
0
static void populateInfo(Info &I, const T *D, const FullComment *C) {
  I.USR = getUSRForDecl(D);
  I.Name = D->getNameAsString();
  populateParentNamespaces(I.Namespace, D);
  if (C) {
    I.Description.emplace_back();
    parseFullComment(C, I.Description.back());
  }
}
コード例 #5
0
static void
populateParentNamespaces(llvm::SmallVector<Reference, 4> &Namespaces,
                         const T *D) {
  const auto *DC = dyn_cast<DeclContext>(D);
  while ((DC = DC->getParent())) {
    if (const auto *N = dyn_cast<NamespaceDecl>(DC))
      Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
                              InfoType::IT_namespace);
    else if (const auto *N = dyn_cast<RecordDecl>(DC))
      Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
                              InfoType::IT_record);
    else if (const auto *N = dyn_cast<FunctionDecl>(DC))
      Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
                              InfoType::IT_function);
    else if (const auto *N = dyn_cast<EnumDecl>(DC))
      Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
                              InfoType::IT_enum);
  }
}
コード例 #6
0
static void parseBases(RecordInfo &I, const CXXRecordDecl *D) {
  // Don't parse bases if this isn't a definition.
  if (!D->isThisDeclarationADefinition())
    return;
  for (const CXXBaseSpecifier &B : D->bases()) {
    if (B.isVirtual())
      continue;
    if (const auto *P = getDeclForType(B.getType()))
      I.Parents.emplace_back(getUSRForDecl(P), P->getNameAsString(),
                             InfoType::IT_record);
    else
      I.Parents.emplace_back(B.getType().getAsString());
  }
  for (const CXXBaseSpecifier &B : D->vbases()) {
    if (const auto *P = getDeclForType(B.getType()))
      I.VirtualParents.emplace_back(getUSRForDecl(P), P->getNameAsString(),
                                    InfoType::IT_record);
    else
      I.VirtualParents.emplace_back(B.getType().getAsString());
  }
}
コード例 #7
0
static void parseFields(RecordInfo &I, const RecordDecl *D, bool PublicOnly) {
  for (const FieldDecl *F : D->fields()) {
    if (PublicOnly && !isPublic(F->getAccessUnsafe(), F->getLinkageInternal()))
      continue;
    if (const auto *T = getDeclForType(F->getTypeSourceInfo()->getType())) {
      // Use getAccessUnsafe so that we just get the default AS_none if it's not
      // valid, as opposed to an assert.
      if (const auto *N = dyn_cast<EnumDecl>(T)) {
        I.Members.emplace_back(getUSRForDecl(T), N->getNameAsString(),
                               InfoType::IT_enum, F->getNameAsString(),
                               N->getAccessUnsafe());
        continue;
      } else if (const auto *N = dyn_cast<RecordDecl>(T)) {
        I.Members.emplace_back(getUSRForDecl(T), N->getNameAsString(),
                               InfoType::IT_record, F->getNameAsString(),
                               N->getAccessUnsafe());
        continue;
      }
    }
    I.Members.emplace_back(F->getTypeSourceInfo()->getType().getAsString(),
                           F->getNameAsString(), F->getAccessUnsafe());
  }
}
コード例 #8
0
std::unique_ptr<Info> emitInfo(const CXXMethodDecl *D, const FullComment *FC,
                               int LineNumber, llvm::StringRef File,
                               bool PublicOnly) {
  if (PublicOnly && !isPublic(D->getAccess(), D->getLinkageInternal()))
    return nullptr;
  FunctionInfo Func;
  populateFunctionInfo(Func, D, FC, LineNumber, File);
  Func.IsMethod = true;

  SymbolID ParentUSR = getUSRForDecl(D->getParent());
  Func.Parent = Reference{ParentUSR, D->getParent()->getNameAsString(),
                          InfoType::IT_record};
  Func.Access = D->getAccess();

  // Wrap in enclosing scope
  auto I = llvm::make_unique<RecordInfo>();
  I->USR = ParentUSR;
  I->ChildFunctions.emplace_back(std::move(Func));
  return std::unique_ptr<Info>{std::move(I)};
}
コード例 #9
0
  void HandleTranslationUnit(ASTContext &Context) override {
    const auto &SourceMgr = Context.getSourceManager();
    // The file we look for the USR in will always be the main source file.
    const auto Point = SourceMgr.getLocForStartOfFile(
        SourceMgr.getMainFileID()).getLocWithOffset(SymbolOffset);
    if (!Point.isValid())
      return;
    const NamedDecl *FoundDecl = nullptr;
    if (OldName.empty()) {
      FoundDecl = getNamedDeclAt(Context, Point);
    } else {
      FoundDecl = getNamedDeclFor(Context, OldName);
    }
    if (FoundDecl == nullptr) {
      FullSourceLoc FullLoc(Point, SourceMgr);
      errs() << "clang-rename: could not find symbol at "
             << SourceMgr.getFilename(Point) << ":"
             << FullLoc.getSpellingLineNumber() << ":"
             << FullLoc.getSpellingColumnNumber() << " (offset " << SymbolOffset
             << ").\n";
      return;
    }

    // If the decl is a constructor or destructor, we want to instead take the
    // decl of the parent record.
    if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(FoundDecl))
      FoundDecl = CtorDecl->getParent();
    else if (const auto *DtorDecl = dyn_cast<CXXDestructorDecl>(FoundDecl))
      FoundDecl = DtorDecl->getParent();

    // If the decl is in any way relatedpp to a class, we want to make sure we
    // search for the constructor and destructor as well as everything else.
    if (const auto *Record = dyn_cast<CXXRecordDecl>(FoundDecl))
      *USRs = getAllConstructorUSRs(Record);

    USRs->push_back(getUSRForDecl(FoundDecl));
    *SpellingName = FoundDecl->getNameAsString();
  }