1bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek//===--- RewriterTestContext.h ----------------------------------*- C++ -*-===// 2bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek// 3bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek// The LLVM Compiler Infrastructure 4bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek// 5bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek// This file is distributed under the University of Illinois Open Source 6bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek// License. See LICENSE.TXT for details. 7bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek// 8bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek//===----------------------------------------------------------------------===// 9bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek// 10bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek// This file defines a utility class for Rewriter related tests. 11bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek// 12bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek//===----------------------------------------------------------------------===// 13bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek 14bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek#ifndef LLVM_CLANG_REWRITER_TEST_CONTEXT_H 15bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek#define LLVM_CLANG_REWRITER_TEST_CONTEXT_H 16bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek 17bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek#include "clang/Basic/Diagnostic.h" 1899eb4a7920667d23a89df8fcc6429d12b36e4d57Douglas Gregor#include "clang/Basic/DiagnosticOptions.h" 19bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek#include "clang/Basic/FileManager.h" 20bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek#include "clang/Basic/LangOptions.h" 21bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek#include "clang/Basic/SourceManager.h" 22bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek#include "clang/Frontend/TextDiagnosticPrinter.h" 23305c613af6cfc40e519c75d9d2c84c6fa9a841c0Ted Kremenek#include "clang/Rewrite/Core/Rewriter.h" 247b699ac3ac8ce48cf9e9387f6b6830f3a8d409d5Manuel Klimek#include "llvm/Support/FileSystem.h" 25bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek#include "llvm/Support/Path.h" 26bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek#include "llvm/Support/raw_ostream.h" 27bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek 28bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimeknamespace clang { 29bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek 30bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek/// \brief A class that sets up a ready to use Rewriter. 31bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek/// 32bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek/// Useful in unit tests that need a Rewriter. Creates all dependencies 33bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek/// of a Rewriter with default values for testing and provides convenience 34bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek/// methods, which help with writing tests that change files. 35bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimekclass RewriterTestContext { 36bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek public: 37bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek RewriterTestContext() 3899eb4a7920667d23a89df8fcc6429d12b36e4d57Douglas Gregor : DiagOpts(new DiagnosticOptions()), 39cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko Diagnostics(IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), 4099eb4a7920667d23a89df8fcc6429d12b36e4d57Douglas Gregor &*DiagOpts), 4199eb4a7920667d23a89df8fcc6429d12b36e4d57Douglas Gregor DiagnosticPrinter(llvm::outs(), &*DiagOpts), 42bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek Files((FileSystemOptions())), 43bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek Sources(Diagnostics, Files), 44bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek Rewrite(Sources, Options) { 45bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek Diagnostics.setClient(&DiagnosticPrinter, false); 46bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek } 47bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek 485bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola ~RewriterTestContext() {} 49bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek 50bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek FileID createInMemoryFile(StringRef Name, StringRef Content) { 51bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek const llvm::MemoryBuffer *Source = 52bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek llvm::MemoryBuffer::getMemBuffer(Content); 53bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek const FileEntry *Entry = 54bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek Files.getVirtualFile(Name, Source->getBufferSize(), 0); 55bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek Sources.overrideFileContents(Entry, Source, true); 56bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek assert(Entry != NULL); 57bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek return Sources.createFileID(Entry, SourceLocation(), SrcMgr::C_User); 58bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek } 59bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek 605bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola // FIXME: this code is mostly a duplicate of 615bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola // unittests/Tooling/RefactoringTest.cpp. Figure out a way to share it. 62bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek FileID createOnDiskFile(StringRef Name, StringRef Content) { 635bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola SmallString<1024> Path; 645bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola int FD; 655bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola llvm::error_code EC = 661ec4a86a867fc04f35d13bc9e33b04cf2171fe41Rafael Espindola llvm::sys::fs::createTemporaryFile(Name, "", FD, Path); 675bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola assert(!EC); 685bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola (void)EC; 695bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola 705bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola llvm::raw_fd_ostream OutStream(FD, true); 71bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek OutStream << Content; 72bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek OutStream.close(); 73bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek const FileEntry *File = Files.getFile(Path); 74bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek assert(File != NULL); 755bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola 765bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola StringRef Found = TemporaryFiles.GetOrCreateValue(Name, Path.str()).second; 775bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola assert(Found == Path); 785bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola (void)Found; 79bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek return Sources.createFileID(File, SourceLocation(), SrcMgr::C_User); 80bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek } 81bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek 82bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek SourceLocation getLocation(FileID ID, unsigned Line, unsigned Column) { 83bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek SourceLocation Result = Sources.translateFileLineCol( 84bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek Sources.getFileEntryForID(ID), Line, Column); 85bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek assert(Result.isValid()); 86bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek return Result; 87bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek } 88bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek 89bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek std::string getRewrittenText(FileID ID) { 90bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek std::string Result; 91bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek llvm::raw_string_ostream OS(Result); 92bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek Rewrite.getEditBuffer(ID).write(OS); 93d6f6569bf693da3f8efd8ce7ae93fbbfccf09753Manuel Klimek OS.flush(); 94bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek return Result; 95bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek } 96bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek 97bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek std::string getFileContentFromDisk(StringRef Name) { 985bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola std::string Path = TemporaryFiles.lookup(Name); 995bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola assert(!Path.empty()); 100bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek // We need to read directly from the FileManager without relaying through 101bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek // a FileEntry, as otherwise we'd read through an already opened file 102bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek // descriptor, which might not see the changes made. 103bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek // FIXME: Figure out whether there is a way to get the SourceManger to 104bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek // reopen the file. 105bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek return Files.getBufferForFile(Path, NULL)->getBuffer(); 106bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek } 107bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek 108cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts; 109bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek DiagnosticsEngine Diagnostics; 110bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek TextDiagnosticPrinter DiagnosticPrinter; 111bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek FileManager Files; 112bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek SourceManager Sources; 113bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek LangOptions Options; 114bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek Rewriter Rewrite; 115bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek 1167b699ac3ac8ce48cf9e9387f6b6830f3a8d409d5Manuel Klimek // Will be set once on disk files are generated. 1175bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola llvm::StringMap<std::string> TemporaryFiles; 118bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek}; 119bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek 120bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek} // end namespace clang 121bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek 122bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek#endif 123