Home | History | Annotate | Download | only in Tooling
      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:
     37    RewriterTestContext()
     38        : DiagOpts(new DiagnosticOptions()),
     39          Diagnostics(IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
     40                      &*DiagOpts),
     41          DiagnosticPrinter(llvm::outs(), &*DiagOpts),
     42          InMemoryFileSystem(new vfs::InMemoryFileSystem),
     43          OverlayFileSystem(
     44              new vfs::OverlayFileSystem(vfs::getRealFileSystem())),
     45          Files(FileSystemOptions(), OverlayFileSystem),
     46          Sources(Diagnostics, Files), Rewrite(Sources, Options) {
     47     Diagnostics.setClient(&DiagnosticPrinter, false);
     48     // FIXME: To make these tests truly in-memory, we need to overlay the
     49     // builtin headers.
     50     OverlayFileSystem->pushOverlay(InMemoryFileSystem);
     51   }
     52 
     53   ~RewriterTestContext() {}
     54 
     55   FileID createInMemoryFile(StringRef Name, StringRef Content) {
     56     std::unique_ptr<llvm::MemoryBuffer> Source =
     57         llvm::MemoryBuffer::getMemBuffer(Content);
     58     InMemoryFileSystem->addFile(Name, 0, std::move(Source));
     59 
     60     const FileEntry *Entry = Files.getFile(Name);
     61     assert(Entry != nullptr);
     62     return Sources.createFileID(Entry, SourceLocation(), SrcMgr::C_User);
     63   }
     64 
     65   // FIXME: this code is mostly a duplicate of
     66   // unittests/Tooling/RefactoringTest.cpp. Figure out a way to share it.
     67   FileID createOnDiskFile(StringRef Name, StringRef Content) {
     68     SmallString<1024> Path;
     69     int FD;
     70     std::error_code EC = llvm::sys::fs::createTemporaryFile(Name, "", FD, Path);
     71     assert(!EC);
     72     (void)EC;
     73 
     74     llvm::raw_fd_ostream OutStream(FD, true);
     75     OutStream << Content;
     76     OutStream.close();
     77     const FileEntry *File = Files.getFile(Path);
     78     assert(File != nullptr);
     79 
     80     StringRef Found =
     81         TemporaryFiles.insert(std::make_pair(Name, Path.str())).first->second;
     82     assert(Found == Path);
     83     (void)Found;
     84     return Sources.createFileID(File, SourceLocation(), SrcMgr::C_User);
     85   }
     86 
     87   SourceLocation getLocation(FileID ID, unsigned Line, unsigned Column) {
     88     SourceLocation Result = Sources.translateFileLineCol(
     89         Sources.getFileEntryForID(ID), Line, Column);
     90     assert(Result.isValid());
     91     return Result;
     92   }
     93 
     94   std::string getRewrittenText(FileID ID) {
     95     std::string Result;
     96     llvm::raw_string_ostream OS(Result);
     97     Rewrite.getEditBuffer(ID).write(OS);
     98     OS.flush();
     99     return Result;
    100   }
    101 
    102   std::string getFileContentFromDisk(StringRef Name) {
    103     std::string Path = TemporaryFiles.lookup(Name);
    104     assert(!Path.empty());
    105     // We need to read directly from the FileManager without relaying through
    106     // a FileEntry, as otherwise we'd read through an already opened file
    107     // descriptor, which might not see the changes made.
    108     // FIXME: Figure out whether there is a way to get the SourceManger to
    109     // reopen the file.
    110     auto FileBuffer = Files.getBufferForFile(Path);
    111     return (*FileBuffer)->getBuffer();
    112   }
    113 
    114   IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
    115   DiagnosticsEngine Diagnostics;
    116   TextDiagnosticPrinter DiagnosticPrinter;
    117   IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem;
    118   IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem;
    119   FileManager Files;
    120   SourceManager Sources;
    121   LangOptions Options;
    122   Rewriter Rewrite;
    123 
    124   // Will be set once on disk files are generated.
    125   llvm::StringMap<std::string> TemporaryFiles;
    126 };
    127 
    128 } // end namespace clang
    129 
    130 #endif
    131