blob: eee7ea1873b802bad1d7db951324b350095fd9bb [file] [log] [blame]
Manuel Klimek78d084d2012-05-22 17:01:35 +00001//===--- 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
Benjamin Kramer2f5db8b2014-08-13 16:25:19 +000014#ifndef LLVM_CLANG_UNITTESTS_TOOLING_REWRITERTESTCONTEXT_H
15#define LLVM_CLANG_UNITTESTS_TOOLING_REWRITERTESTCONTEXT_H
Manuel Klimek78d084d2012-05-22 17:01:35 +000016
17#include "clang/Basic/Diagnostic.h"
Douglas Gregor275e8832012-10-23 22:55:10 +000018#include "clang/Basic/DiagnosticOptions.h"
Manuel Klimek78d084d2012-05-22 17:01:35 +000019#include "clang/Basic/FileManager.h"
20#include "clang/Basic/LangOptions.h"
21#include "clang/Basic/SourceManager.h"
Manuel Klimek78d084d2012-05-22 17:01:35 +000022#include "clang/Frontend/TextDiagnosticPrinter.h"
Ted Kremenekcdf81492012-09-01 05:09:24 +000023#include "clang/Rewrite/Core/Rewriter.h"
Manuel Klimek0a8b9cd2012-06-06 21:28:13 +000024#include "llvm/Support/FileSystem.h"
Manuel Klimek78d084d2012-05-22 17:01:35 +000025#include "llvm/Support/Path.h"
26#include "llvm/Support/raw_ostream.h"
27
28namespace 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.
35class RewriterTestContext {
36 public:
Benjamin Kramera25dcfd2015-10-05 13:55:14 +000037 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) {
Manuel Klimek78d084d2012-05-22 17:01:35 +000047 Diagnostics.setClient(&DiagnosticPrinter, false);
Benjamin Kramera25dcfd2015-10-05 13:55:14 +000048 // FIXME: To make these tests truly in-memory, we need to overlay the
49 // builtin headers.
50 OverlayFileSystem->pushOverlay(InMemoryFileSystem);
Manuel Klimek78d084d2012-05-22 17:01:35 +000051 }
52
Angel Garcia Gomez637d1e62015-10-20 13:23:58 +000053 ~RewriterTestContext() {}
Manuel Klimek78d084d2012-05-22 17:01:35 +000054
55 FileID createInMemoryFile(StringRef Name, StringRef Content) {
Rafael Espindolad87f8d72014-08-27 20:03:29 +000056 std::unique_ptr<llvm::MemoryBuffer> Source =
57 llvm::MemoryBuffer::getMemBuffer(Content);
Benjamin Kramera25dcfd2015-10-05 13:55:14 +000058 InMemoryFileSystem->addFile(Name, 0, std::move(Source));
59
60 const FileEntry *Entry = Files.getFile(Name);
Craig Topper416fa342014-06-08 08:38:12 +000061 assert(Entry != nullptr);
Manuel Klimek78d084d2012-05-22 17:01:35 +000062 return Sources.createFileID(Entry, SourceLocation(), SrcMgr::C_User);
63 }
64
Rafael Espindola8b960942013-06-26 21:02:22 +000065 // FIXME: this code is mostly a duplicate of
66 // unittests/Tooling/RefactoringTest.cpp. Figure out a way to share it.
Manuel Klimek78d084d2012-05-22 17:01:35 +000067 FileID createOnDiskFile(StringRef Name, StringRef Content) {
Rafael Espindola8b960942013-06-26 21:02:22 +000068 SmallString<1024> Path;
69 int FD;
Rafael Espindolac0809172014-06-12 14:02:15 +000070 std::error_code EC = llvm::sys::fs::createTemporaryFile(Name, "", FD, Path);
Rafael Espindola8b960942013-06-26 21:02:22 +000071 assert(!EC);
72 (void)EC;
73
74 llvm::raw_fd_ostream OutStream(FD, true);
Manuel Klimek78d084d2012-05-22 17:01:35 +000075 OutStream << Content;
76 OutStream.close();
77 const FileEntry *File = Files.getFile(Path);
Craig Topper416fa342014-06-08 08:38:12 +000078 assert(File != nullptr);
Rafael Espindola8b960942013-06-26 21:02:22 +000079
David Blaikie13156b62014-11-19 03:06:06 +000080 StringRef Found =
81 TemporaryFiles.insert(std::make_pair(Name, Path.str())).first->second;
Rafael Espindola8b960942013-06-26 21:02:22 +000082 assert(Found == Path);
83 (void)Found;
Manuel Klimek78d084d2012-05-22 17:01:35 +000084 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);
Manuel Klimekee56b542012-06-05 20:16:30 +000098 OS.flush();
Manuel Klimek78d084d2012-05-22 17:01:35 +000099 return Result;
100 }
101
102 std::string getFileContentFromDisk(StringRef Name) {
Rafael Espindola8b960942013-06-26 21:02:22 +0000103 std::string Path = TemporaryFiles.lookup(Name);
104 assert(!Path.empty());
Manuel Klimek78d084d2012-05-22 17:01:35 +0000105 // 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.
Benjamin Kramera8857962014-10-26 22:44:13 +0000110 auto FileBuffer = Files.getBufferForFile(Path);
111 return (*FileBuffer)->getBuffer();
Manuel Klimek78d084d2012-05-22 17:01:35 +0000112 }
113
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000114 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
Manuel Klimek78d084d2012-05-22 17:01:35 +0000115 DiagnosticsEngine Diagnostics;
116 TextDiagnosticPrinter DiagnosticPrinter;
Benjamin Kramera25dcfd2015-10-05 13:55:14 +0000117 IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem;
118 IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem;
Manuel Klimek78d084d2012-05-22 17:01:35 +0000119 FileManager Files;
120 SourceManager Sources;
121 LangOptions Options;
122 Rewriter Rewrite;
123
Manuel Klimek0a8b9cd2012-06-06 21:28:13 +0000124 // Will be set once on disk files are generated.
Rafael Espindola8b960942013-06-26 21:02:22 +0000125 llvm::StringMap<std::string> TemporaryFiles;
Manuel Klimek78d084d2012-05-22 17:01:35 +0000126};
127
128} // end namespace clang
129
130#endif