119 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			119 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C++
		
	
	
	
//===--- tools/extra/clang-rename/USRFindingAction.cpp - Clang rename tool ===//
 | 
						|
//
 | 
						|
//                     The LLVM Compiler Infrastructure
 | 
						|
//
 | 
						|
// This file is distributed under the University of Illinois Open Source
 | 
						|
// License. See LICENSE.TXT for details.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
///
 | 
						|
/// \file
 | 
						|
/// \brief Provides an action to rename every symbol at a point.
 | 
						|
///
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "USRFindingAction.h"
 | 
						|
#include "USRFinder.h"
 | 
						|
#include "clang/AST/AST.h"
 | 
						|
#include "clang/AST/ASTConsumer.h"
 | 
						|
#include "clang/AST/ASTContext.h"
 | 
						|
#include "clang/Basic/FileManager.h"
 | 
						|
#include "clang/Frontend/CompilerInstance.h"
 | 
						|
#include "clang/Frontend/FrontendAction.h"
 | 
						|
#include "clang/Lex/Lexer.h"
 | 
						|
#include "clang/Lex/Preprocessor.h"
 | 
						|
#include "clang/Tooling/CommonOptionsParser.h"
 | 
						|
#include "clang/Tooling/Refactoring.h"
 | 
						|
#include "clang/Tooling/Tooling.h"
 | 
						|
#include <ctype.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string>
 | 
						|
#include <vector>
 | 
						|
 | 
						|
using namespace llvm;
 | 
						|
 | 
						|
namespace clang {
 | 
						|
namespace rename {
 | 
						|
 | 
						|
// 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;
 | 
						|
}
 | 
						|
 | 
						|
struct NamedDeclFindingConsumer : public ASTConsumer {
 | 
						|
  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 = getNamedDeclAt(Context, Point);
 | 
						|
    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();
 | 
						|
  }
 | 
						|
 | 
						|
  unsigned SymbolOffset;
 | 
						|
  std::string *SpellingName;
 | 
						|
  std::vector<std::string> *USRs;
 | 
						|
};
 | 
						|
 | 
						|
std::unique_ptr<ASTConsumer>
 | 
						|
USRFindingAction::newASTConsumer() {
 | 
						|
  std::unique_ptr<NamedDeclFindingConsumer> Consumer(
 | 
						|
      new NamedDeclFindingConsumer);
 | 
						|
  SpellingName = "";
 | 
						|
  Consumer->SymbolOffset = SymbolOffset;
 | 
						|
  Consumer->USRs = &USRs;
 | 
						|
  Consumer->SpellingName = &SpellingName;
 | 
						|
  return std::move(Consumer);
 | 
						|
}
 | 
						|
 | 
						|
} // namespace rename
 | 
						|
} // namespace clang
 |