blob: 13c42029fc7f3b010a6d43500a14c350233b412e [file] [log] [blame]
Manuel Klimekbfbfee52012-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
14#ifndef LLVM_CLANG_REWRITER_TEST_CONTEXT_H
15#define LLVM_CLANG_REWRITER_TEST_CONTEXT_H
16
17#include "clang/Basic/Diagnostic.h"
Douglas Gregor99eb4a72012-10-23 22:55:10 +000018#include "clang/Basic/DiagnosticOptions.h"
Manuel Klimekbfbfee52012-05-22 17:01:35 +000019#include "clang/Basic/FileManager.h"
20#include "clang/Basic/LangOptions.h"
21#include "clang/Basic/SourceManager.h"
Manuel Klimekbfbfee52012-05-22 17:01:35 +000022#include "clang/Frontend/TextDiagnosticPrinter.h"
Ted Kremenek305c6132012-09-01 05:09:24 +000023#include "clang/Rewrite/Core/Rewriter.h"
Manuel Klimek7b699ac2012-06-06 21:28:13 +000024#include "llvm/Support/FileSystem.h"
Manuel Klimekbfbfee52012-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:
37 RewriterTestContext()
Douglas Gregor99eb4a72012-10-23 22:55:10 +000038 : DiagOpts(new DiagnosticOptions()),
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +000039 Diagnostics(IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
Douglas Gregor99eb4a72012-10-23 22:55:10 +000040 &*DiagOpts),
41 DiagnosticPrinter(llvm::outs(), &*DiagOpts),
Manuel Klimekbfbfee52012-05-22 17:01:35 +000042 Files((FileSystemOptions())),
43 Sources(Diagnostics, Files),
44 Rewrite(Sources, Options) {
45 Diagnostics.setClient(&DiagnosticPrinter, false);
46 }
47
48 ~RewriterTestContext() {
Manuel Klimek7b699ac2012-06-06 21:28:13 +000049 if (!TemporaryDirectory.empty()) {
50 uint32_t RemovedCount = 0;
51 llvm::sys::fs::remove_all(TemporaryDirectory.str(), RemovedCount);
52 }
Manuel Klimekbfbfee52012-05-22 17:01:35 +000053 }
54
55 FileID createInMemoryFile(StringRef Name, StringRef Content) {
56 const llvm::MemoryBuffer *Source =
57 llvm::MemoryBuffer::getMemBuffer(Content);
58 const FileEntry *Entry =
59 Files.getVirtualFile(Name, Source->getBufferSize(), 0);
60 Sources.overrideFileContents(Entry, Source, true);
61 assert(Entry != NULL);
62 return Sources.createFileID(Entry, SourceLocation(), SrcMgr::C_User);
63 }
64
65 FileID createOnDiskFile(StringRef Name, StringRef Content) {
Manuel Klimek7b699ac2012-06-06 21:28:13 +000066 if (TemporaryDirectory.empty()) {
67 int FD;
Benjamin Kramerc2a50d42012-06-07 09:57:21 +000068 bool error =
69 llvm::sys::fs::unique_file("rewriter-test-%%-%%-%%-%%/anchor", FD,
70 TemporaryDirectory);
71 assert(!error); (void)error;
Manuel Klimek7b699ac2012-06-06 21:28:13 +000072 llvm::raw_fd_ostream Closer(FD, /*shouldClose=*/true);
73 TemporaryDirectory = llvm::sys::path::parent_path(TemporaryDirectory);
Manuel Klimekbfbfee52012-05-22 17:01:35 +000074 }
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +000075 SmallString<1024> Path(TemporaryDirectory);
Manuel Klimekbfbfee52012-05-22 17:01:35 +000076 llvm::sys::path::append(Path, Name);
77 std::string ErrorInfo;
78 llvm::raw_fd_ostream OutStream(Path.c_str(),
79 ErrorInfo, llvm::raw_fd_ostream::F_Binary);
80 assert(ErrorInfo.empty());
81 OutStream << Content;
82 OutStream.close();
83 const FileEntry *File = Files.getFile(Path);
84 assert(File != NULL);
85 return Sources.createFileID(File, SourceLocation(), SrcMgr::C_User);
86 }
87
88 SourceLocation getLocation(FileID ID, unsigned Line, unsigned Column) {
89 SourceLocation Result = Sources.translateFileLineCol(
90 Sources.getFileEntryForID(ID), Line, Column);
91 assert(Result.isValid());
92 return Result;
93 }
94
95 std::string getRewrittenText(FileID ID) {
96 std::string Result;
97 llvm::raw_string_ostream OS(Result);
98 Rewrite.getEditBuffer(ID).write(OS);
Manuel Klimekd6f65692012-06-05 20:16:30 +000099 OS.flush();
Manuel Klimekbfbfee52012-05-22 17:01:35 +0000100 return Result;
101 }
102
103 std::string getFileContentFromDisk(StringRef Name) {
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +0000104 SmallString<1024> Path(TemporaryDirectory.str());
Manuel Klimekbfbfee52012-05-22 17:01:35 +0000105 llvm::sys::path::append(Path, Name);
106 // We need to read directly from the FileManager without relaying through
107 // a FileEntry, as otherwise we'd read through an already opened file
108 // descriptor, which might not see the changes made.
109 // FIXME: Figure out whether there is a way to get the SourceManger to
110 // reopen the file.
111 return Files.getBufferForFile(Path, NULL)->getBuffer();
112 }
113
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +0000114 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
Manuel Klimekbfbfee52012-05-22 17:01:35 +0000115 DiagnosticsEngine Diagnostics;
116 TextDiagnosticPrinter DiagnosticPrinter;
117 FileManager Files;
118 SourceManager Sources;
119 LangOptions Options;
120 Rewriter Rewrite;
121
Manuel Klimek7b699ac2012-06-06 21:28:13 +0000122 // Will be set once on disk files are generated.
123 SmallString<128> TemporaryDirectory;
Manuel Klimekbfbfee52012-05-22 17:01:35 +0000124};
125
126} // end namespace clang
127
128#endif