1*67e74705SXin Li //===--- RewriterTestContext.h ----------------------------------*- C++ -*-===// 2*67e74705SXin Li // 3*67e74705SXin Li // The LLVM Compiler Infrastructure 4*67e74705SXin Li // 5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source 6*67e74705SXin Li // License. See LICENSE.TXT for details. 7*67e74705SXin Li // 8*67e74705SXin Li //===----------------------------------------------------------------------===// 9*67e74705SXin Li // 10*67e74705SXin Li // This file defines a utility class for Rewriter related tests. 11*67e74705SXin Li // 12*67e74705SXin Li //===----------------------------------------------------------------------===// 13*67e74705SXin Li 14*67e74705SXin Li #ifndef LLVM_CLANG_UNITTESTS_TOOLING_REWRITERTESTCONTEXT_H 15*67e74705SXin Li #define LLVM_CLANG_UNITTESTS_TOOLING_REWRITERTESTCONTEXT_H 16*67e74705SXin Li 17*67e74705SXin Li #include "clang/Basic/Diagnostic.h" 18*67e74705SXin Li #include "clang/Basic/DiagnosticOptions.h" 19*67e74705SXin Li #include "clang/Basic/FileManager.h" 20*67e74705SXin Li #include "clang/Basic/LangOptions.h" 21*67e74705SXin Li #include "clang/Basic/SourceManager.h" 22*67e74705SXin Li #include "clang/Frontend/TextDiagnosticPrinter.h" 23*67e74705SXin Li #include "clang/Rewrite/Core/Rewriter.h" 24*67e74705SXin Li #include "llvm/Support/FileSystem.h" 25*67e74705SXin Li #include "llvm/Support/Path.h" 26*67e74705SXin Li #include "llvm/Support/raw_ostream.h" 27*67e74705SXin Li 28*67e74705SXin Li namespace clang { 29*67e74705SXin Li 30*67e74705SXin Li /// \brief A class that sets up a ready to use Rewriter. 31*67e74705SXin Li /// 32*67e74705SXin Li /// Useful in unit tests that need a Rewriter. Creates all dependencies 33*67e74705SXin Li /// of a Rewriter with default values for testing and provides convenience 34*67e74705SXin Li /// methods, which help with writing tests that change files. 35*67e74705SXin Li class RewriterTestContext { 36*67e74705SXin Li public: RewriterTestContext()37*67e74705SXin Li RewriterTestContext() 38*67e74705SXin Li : DiagOpts(new DiagnosticOptions()), 39*67e74705SXin Li Diagnostics(IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), 40*67e74705SXin Li &*DiagOpts), 41*67e74705SXin Li DiagnosticPrinter(llvm::outs(), &*DiagOpts), 42*67e74705SXin Li InMemoryFileSystem(new vfs::InMemoryFileSystem), 43*67e74705SXin Li OverlayFileSystem( 44*67e74705SXin Li new vfs::OverlayFileSystem(vfs::getRealFileSystem())), 45*67e74705SXin Li Files(FileSystemOptions(), OverlayFileSystem), 46*67e74705SXin Li Sources(Diagnostics, Files), Rewrite(Sources, Options) { 47*67e74705SXin Li Diagnostics.setClient(&DiagnosticPrinter, false); 48*67e74705SXin Li // FIXME: To make these tests truly in-memory, we need to overlay the 49*67e74705SXin Li // builtin headers. 50*67e74705SXin Li OverlayFileSystem->pushOverlay(InMemoryFileSystem); 51*67e74705SXin Li } 52*67e74705SXin Li ~RewriterTestContext()53*67e74705SXin Li ~RewriterTestContext() {} 54*67e74705SXin Li createInMemoryFile(StringRef Name,StringRef Content)55*67e74705SXin Li FileID createInMemoryFile(StringRef Name, StringRef Content) { 56*67e74705SXin Li std::unique_ptr<llvm::MemoryBuffer> Source = 57*67e74705SXin Li llvm::MemoryBuffer::getMemBuffer(Content); 58*67e74705SXin Li InMemoryFileSystem->addFile(Name, 0, std::move(Source)); 59*67e74705SXin Li 60*67e74705SXin Li const FileEntry *Entry = Files.getFile(Name); 61*67e74705SXin Li assert(Entry != nullptr); 62*67e74705SXin Li return Sources.createFileID(Entry, SourceLocation(), SrcMgr::C_User); 63*67e74705SXin Li } 64*67e74705SXin Li 65*67e74705SXin Li // FIXME: this code is mostly a duplicate of 66*67e74705SXin Li // unittests/Tooling/RefactoringTest.cpp. Figure out a way to share it. createOnDiskFile(StringRef Name,StringRef Content)67*67e74705SXin Li FileID createOnDiskFile(StringRef Name, StringRef Content) { 68*67e74705SXin Li SmallString<1024> Path; 69*67e74705SXin Li int FD; 70*67e74705SXin Li std::error_code EC = llvm::sys::fs::createTemporaryFile(Name, "", FD, Path); 71*67e74705SXin Li assert(!EC); 72*67e74705SXin Li (void)EC; 73*67e74705SXin Li 74*67e74705SXin Li llvm::raw_fd_ostream OutStream(FD, true); 75*67e74705SXin Li OutStream << Content; 76*67e74705SXin Li OutStream.close(); 77*67e74705SXin Li const FileEntry *File = Files.getFile(Path); 78*67e74705SXin Li assert(File != nullptr); 79*67e74705SXin Li 80*67e74705SXin Li StringRef Found = 81*67e74705SXin Li TemporaryFiles.insert(std::make_pair(Name, Path.str())).first->second; 82*67e74705SXin Li assert(Found == Path); 83*67e74705SXin Li (void)Found; 84*67e74705SXin Li return Sources.createFileID(File, SourceLocation(), SrcMgr::C_User); 85*67e74705SXin Li } 86*67e74705SXin Li getLocation(FileID ID,unsigned Line,unsigned Column)87*67e74705SXin Li SourceLocation getLocation(FileID ID, unsigned Line, unsigned Column) { 88*67e74705SXin Li SourceLocation Result = Sources.translateFileLineCol( 89*67e74705SXin Li Sources.getFileEntryForID(ID), Line, Column); 90*67e74705SXin Li assert(Result.isValid()); 91*67e74705SXin Li return Result; 92*67e74705SXin Li } 93*67e74705SXin Li getRewrittenText(FileID ID)94*67e74705SXin Li std::string getRewrittenText(FileID ID) { 95*67e74705SXin Li std::string Result; 96*67e74705SXin Li llvm::raw_string_ostream OS(Result); 97*67e74705SXin Li Rewrite.getEditBuffer(ID).write(OS); 98*67e74705SXin Li OS.flush(); 99*67e74705SXin Li return Result; 100*67e74705SXin Li } 101*67e74705SXin Li getFileContentFromDisk(StringRef Name)102*67e74705SXin Li std::string getFileContentFromDisk(StringRef Name) { 103*67e74705SXin Li std::string Path = TemporaryFiles.lookup(Name); 104*67e74705SXin Li assert(!Path.empty()); 105*67e74705SXin Li // We need to read directly from the FileManager without relaying through 106*67e74705SXin Li // a FileEntry, as otherwise we'd read through an already opened file 107*67e74705SXin Li // descriptor, which might not see the changes made. 108*67e74705SXin Li // FIXME: Figure out whether there is a way to get the SourceManger to 109*67e74705SXin Li // reopen the file. 110*67e74705SXin Li auto FileBuffer = Files.getBufferForFile(Path); 111*67e74705SXin Li return (*FileBuffer)->getBuffer(); 112*67e74705SXin Li } 113*67e74705SXin Li 114*67e74705SXin Li IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts; 115*67e74705SXin Li DiagnosticsEngine Diagnostics; 116*67e74705SXin Li TextDiagnosticPrinter DiagnosticPrinter; 117*67e74705SXin Li IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem; 118*67e74705SXin Li IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem; 119*67e74705SXin Li FileManager Files; 120*67e74705SXin Li SourceManager Sources; 121*67e74705SXin Li LangOptions Options; 122*67e74705SXin Li Rewriter Rewrite; 123*67e74705SXin Li 124*67e74705SXin Li // Will be set once on disk files are generated. 125*67e74705SXin Li llvm::StringMap<std::string> TemporaryFiles; 126*67e74705SXin Li }; 127*67e74705SXin Li 128*67e74705SXin Li } // end namespace clang 129*67e74705SXin Li 130*67e74705SXin Li #endif 131