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) { 51ef8225444452a1486bd721f3285301fe84643b00Stephen Hines llvm::MemoryBuffer *Source = llvm::MemoryBuffer::getMemBuffer(Content); 52bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek const FileEntry *Entry = 53bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek Files.getVirtualFile(Name, Source->getBufferSize(), 0); 546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Sources.overrideFileContents(Entry, Source); 55ef8225444452a1486bd721f3285301fe84643b00Stephen Hines assert(Entry != nullptr); 56bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek return Sources.createFileID(Entry, SourceLocation(), SrcMgr::C_User); 57bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek } 58bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek 595bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola // FIXME: this code is mostly a duplicate of 605bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola // unittests/Tooling/RefactoringTest.cpp. Figure out a way to share it. 61bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek FileID createOnDiskFile(StringRef Name, StringRef Content) { 625bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola SmallString<1024> Path; 635bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola int FD; 64ef8225444452a1486bd721f3285301fe84643b00Stephen Hines std::error_code EC = llvm::sys::fs::createTemporaryFile(Name, "", FD, Path); 655bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola assert(!EC); 665bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola (void)EC; 675bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola 685bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola llvm::raw_fd_ostream OutStream(FD, true); 69bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek OutStream << Content; 70bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek OutStream.close(); 71bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek const FileEntry *File = Files.getFile(Path); 72ef8225444452a1486bd721f3285301fe84643b00Stephen Hines assert(File != nullptr); 735bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola 745bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola StringRef Found = TemporaryFiles.GetOrCreateValue(Name, Path.str()).second; 755bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola assert(Found == Path); 765bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola (void)Found; 77bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek return Sources.createFileID(File, SourceLocation(), SrcMgr::C_User); 78bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek } 79bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek 80bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek SourceLocation getLocation(FileID ID, unsigned Line, unsigned Column) { 81bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek SourceLocation Result = Sources.translateFileLineCol( 82bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek Sources.getFileEntryForID(ID), Line, Column); 83bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek assert(Result.isValid()); 84bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek return Result; 85bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek } 86bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek 87bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek std::string getRewrittenText(FileID ID) { 88bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek std::string Result; 89bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek llvm::raw_string_ostream OS(Result); 90bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek Rewrite.getEditBuffer(ID).write(OS); 91d6f6569bf693da3f8efd8ce7ae93fbbfccf09753Manuel Klimek OS.flush(); 92bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek return Result; 93bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek } 94bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek 95bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek std::string getFileContentFromDisk(StringRef Name) { 965bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola std::string Path = TemporaryFiles.lookup(Name); 975bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola assert(!Path.empty()); 98bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek // We need to read directly from the FileManager without relaying through 99bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek // a FileEntry, as otherwise we'd read through an already opened file 100bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek // descriptor, which might not see the changes made. 101bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek // FIXME: Figure out whether there is a way to get the SourceManger to 102bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek // reopen the file. 1036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines std::unique_ptr<const llvm::MemoryBuffer> FileBuffer( 104ef8225444452a1486bd721f3285301fe84643b00Stephen Hines Files.getBufferForFile(Path, nullptr)); 1056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return FileBuffer->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