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