• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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          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 
~RewriterTestContext()53   ~RewriterTestContext() {}
54 
createInMemoryFile(StringRef Name,StringRef Content)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.
createOnDiskFile(StringRef Name,StringRef Content)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 
getLocation(FileID ID,unsigned Line,unsigned Column)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 
getRewrittenText(FileID ID)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 
getFileContentFromDisk(StringRef Name)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