1 //===--- RewriterTestContext.h ----------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines a utility class for Rewriter related tests.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_CLANG_UNITTESTS_TOOLING_REWRITERTESTCONTEXT_H
15 #define LLVM_CLANG_UNITTESTS_TOOLING_REWRITERTESTCONTEXT_H
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"
30 /// \brief A class that sets up a ready to use Rewriter.
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 {
38 : DiagOpts(new DiagnosticOptions()),
39 Diagnostics(IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
41 DiagnosticPrinter(llvm::outs(), &*DiagOpts),
42 InMemoryFileSystem(new vfs::InMemoryFileSystem),
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
50 OverlayFileSystem->pushOverlay(InMemoryFileSystem);
53 ~RewriterTestContext() {}
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));
60 const FileEntry *Entry = Files.getFile(Name);
61 assert(Entry != nullptr);
62 return Sources.createFileID(Entry, SourceLocation(), SrcMgr::C_User);
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;
70 std::error_code EC = llvm::sys::fs::createTemporaryFile(Name, "", FD, Path);
74 llvm::raw_fd_ostream OutStream(FD, true);
77 const FileEntry *File = Files.getFile(Path);
78 assert(File != nullptr);
81 TemporaryFiles.insert(std::make_pair(Name, Path.str())).first->second;
82 assert(Found == Path);
84 return Sources.createFileID(File, SourceLocation(), SrcMgr::C_User);
87 SourceLocation getLocation(FileID ID, unsigned Line, unsigned Column) {
88 SourceLocation Result = Sources.translateFileLineCol(
89 Sources.getFileEntryForID(ID), Line, Column);
90 assert(Result.isValid());
94 std::string getRewrittenText(FileID ID) {
96 llvm::raw_string_ostream OS(Result);
97 Rewrite.getEditBuffer(ID).write(OS);
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
110 auto FileBuffer = Files.getBufferForFile(Path);
111 return (*FileBuffer)->getBuffer();
114 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
115 DiagnosticsEngine Diagnostics;
116 TextDiagnosticPrinter DiagnosticPrinter;
117 IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem;
118 IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem;
120 SourceManager Sources;
124 // Will be set once on disk files are generated.
125 llvm::StringMap<std::string> TemporaryFiles;
128 } // end namespace clang