1f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek//===--- Refactoring.cpp - Framework for clang refactoring tools ----------===//
2f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek//
3f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek//                     The LLVM Compiler Infrastructure
4f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek//
5f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// This file is distributed under the University of Illinois Open Source
6f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// License. See LICENSE.TXT for details.
7f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek//
8f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek//===----------------------------------------------------------------------===//
9f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek//
10f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek//  Implements tools to support refactorings.
11f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek//
12f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek//===----------------------------------------------------------------------===//
13f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek
1402c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor#include "clang/Basic/DiagnosticOptions.h"
15f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include "clang/Basic/FileManager.h"
16f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include "clang/Basic/SourceManager.h"
174967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include "clang/Format/Format.h"
18f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include "clang/Frontend/TextDiagnosticPrinter.h"
19f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include "clang/Lex/Lexer.h"
20305c613af6cfc40e519c75d9d2c84c6fa9a841c0Ted Kremenek#include "clang/Rewrite/Core/Rewriter.h"
21f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include "clang/Tooling/Refactoring.h"
22d11344a728c7ffab17e5557506edfbcbae18d34eAriel J. Bernal#include "llvm/Support/FileSystem.h"
23d11344a728c7ffab17e5557506edfbcbae18d34eAriel J. Bernal#include "llvm/Support/Path.h"
24651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "llvm/Support/raw_os_ostream.h"
25f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek
26f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimeknamespace clang {
27f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimeknamespace tooling {
28f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek
2987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga NainarRefactoringTool::RefactoringTool(
3087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    const CompilationDatabase &Compilations, ArrayRef<std::string> SourcePaths,
3187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    std::shared_ptr<PCHContainerOperations> PCHContainerOps)
3287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    : ClangTool(Compilations, SourcePaths, PCHContainerOps) {}
33f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek
34f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel KlimekReplacements &RefactoringTool::getReplacements() { return Replace; }
35f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek
36d088a5f966c31462280d5ace29febc6889834611Edwin Vaneint RefactoringTool::runAndSave(FrontendActionFactory *ActionFactory) {
37d088a5f966c31462280d5ace29febc6889834611Edwin Vane  if (int Result = run(ActionFactory)) {
38d088a5f966c31462280d5ace29febc6889834611Edwin Vane    return Result;
39d088a5f966c31462280d5ace29febc6889834611Edwin Vane  }
40d088a5f966c31462280d5ace29febc6889834611Edwin Vane
41f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  LangOptions DefaultLangOptions;
4202c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
4302c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor  TextDiagnosticPrinter DiagnosticPrinter(llvm::errs(), &*DiagOpts);
44f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  DiagnosticsEngine Diagnostics(
45cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko      IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()),
4602c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor      &*DiagOpts, &DiagnosticPrinter, false);
47d088a5f966c31462280d5ace29febc6889834611Edwin Vane  SourceManager Sources(Diagnostics, getFiles());
48f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  Rewriter Rewrite(Sources, DefaultLangOptions);
49d088a5f966c31462280d5ace29febc6889834611Edwin Vane
50d088a5f966c31462280d5ace29febc6889834611Edwin Vane  if (!applyAllReplacements(Rewrite)) {
51f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek    llvm::errs() << "Skipped some replacements.\n";
52f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek  }
53d088a5f966c31462280d5ace29febc6889834611Edwin Vane
54d088a5f966c31462280d5ace29febc6889834611Edwin Vane  return saveRewrittenFiles(Rewrite);
55d088a5f966c31462280d5ace29febc6889834611Edwin Vane}
56d088a5f966c31462280d5ace29febc6889834611Edwin Vane
57d088a5f966c31462280d5ace29febc6889834611Edwin Vanebool RefactoringTool::applyAllReplacements(Rewriter &Rewrite) {
58d088a5f966c31462280d5ace29febc6889834611Edwin Vane  return tooling::applyAllReplacements(Replace, Rewrite);
59d088a5f966c31462280d5ace29febc6889834611Edwin Vane}
60d088a5f966c31462280d5ace29febc6889834611Edwin Vane
61d088a5f966c31462280d5ace29febc6889834611Edwin Vaneint RefactoringTool::saveRewrittenFiles(Rewriter &Rewrite) {
626bf97fb15c09db9a0238ccb73be2dbf9cd77a7eeAlp Toker  return Rewrite.overwriteChangedFiles() ? 1 : 0;
63f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek}
64f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek
654967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarbool formatAndApplyAllReplacements(const Replacements &Replaces,
664967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar                                   Rewriter &Rewrite, StringRef Style) {
674967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  SourceManager &SM = Rewrite.getSourceMgr();
684967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  FileManager &Files = SM.getFileManager();
694967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
704967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  auto FileToReplaces = groupReplacementsByFile(Replaces);
714967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
724967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  bool Result = true;
734967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  for (const auto &FileAndReplaces : FileToReplaces) {
744967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    const std::string &FilePath = FileAndReplaces.first;
754967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    auto &CurReplaces = FileAndReplaces.second;
764967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
774967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    const FileEntry *Entry = Files.getFile(FilePath);
784967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    FileID ID = SM.getOrCreateFileID(Entry, SrcMgr::C_User);
794967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    StringRef Code = SM.getBufferData(ID);
804967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
814967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    format::FormatStyle CurStyle = format::getStyle(Style, FilePath, "LLVM");
824967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    auto NewReplacements =
834967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar        format::formatReplacements(Code, CurReplaces, CurStyle);
844967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    if (!NewReplacements) {
854967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      llvm::errs() << llvm::toString(NewReplacements.takeError()) << "\n";
864967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      return false;
874967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    }
884967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    Result = applyAllReplacements(*NewReplacements, Rewrite) && Result;
894967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  }
904967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  return Result;
914967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar}
924967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
93f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} // end namespace tooling
94f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} // end namespace clang
95