blob: ba919d6472b9d1edcd09a28c7cd68dffd8584075 [file] [log] [blame]
Manuel Klimek78d084d2012-05-22 17:01:35 +00001//===--- RewriterTestContext.h ----------------------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Manuel Klimek78d084d2012-05-22 17:01:35 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This file defines a utility class for Rewriter related tests.
10//
11//===----------------------------------------------------------------------===//
12
Benjamin Kramer2f5db8b2014-08-13 16:25:19 +000013#ifndef LLVM_CLANG_UNITTESTS_TOOLING_REWRITERTESTCONTEXT_H
14#define LLVM_CLANG_UNITTESTS_TOOLING_REWRITERTESTCONTEXT_H
Manuel Klimek78d084d2012-05-22 17:01:35 +000015
16#include "clang/Basic/Diagnostic.h"
Douglas Gregor275e8832012-10-23 22:55:10 +000017#include "clang/Basic/DiagnosticOptions.h"
Manuel Klimek78d084d2012-05-22 17:01:35 +000018#include "clang/Basic/FileManager.h"
19#include "clang/Basic/LangOptions.h"
20#include "clang/Basic/SourceManager.h"
Manuel Klimek78d084d2012-05-22 17:01:35 +000021#include "clang/Frontend/TextDiagnosticPrinter.h"
Ted Kremenekcdf81492012-09-01 05:09:24 +000022#include "clang/Rewrite/Core/Rewriter.h"
Manuel Klimek0a8b9cd2012-06-06 21:28:13 +000023#include "llvm/Support/FileSystem.h"
Manuel Klimek78d084d2012-05-22 17:01:35 +000024#include "llvm/Support/Path.h"
25#include "llvm/Support/raw_ostream.h"
26
27namespace clang {
28
29/// \brief A class that sets up a ready to use Rewriter.
30///
31/// Useful in unit tests that need a Rewriter. Creates all dependencies
32/// of a Rewriter with default values for testing and provides convenience
33/// methods, which help with writing tests that change files.
34class RewriterTestContext {
35 public:
Benjamin Kramera25dcfd2015-10-05 13:55:14 +000036 RewriterTestContext()
37 : DiagOpts(new DiagnosticOptions()),
38 Diagnostics(IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
39 &*DiagOpts),
40 DiagnosticPrinter(llvm::outs(), &*DiagOpts),
Jonas Devliegherefc514902018-10-10 13:27:25 +000041 InMemoryFileSystem(new llvm::vfs::InMemoryFileSystem),
Benjamin Kramera25dcfd2015-10-05 13:55:14 +000042 OverlayFileSystem(
Jonas Devliegherefc514902018-10-10 13:27:25 +000043 new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem())),
Benjamin Kramera25dcfd2015-10-05 13:55:14 +000044 Files(FileSystemOptions(), OverlayFileSystem),
45 Sources(Diagnostics, Files), Rewrite(Sources, Options) {
Jonas Devliegherefc514902018-10-10 13:27:25 +000046 Diagnostics.setClient(&DiagnosticPrinter, false);
47 // FIXME: To make these tests truly in-memory, we need to overlay the
48 // builtin headers.
49 OverlayFileSystem->pushOverlay(InMemoryFileSystem);
Manuel Klimek78d084d2012-05-22 17:01:35 +000050 }
51
Angel Garcia Gomez637d1e62015-10-20 13:23:58 +000052 ~RewriterTestContext() {}
Manuel Klimek78d084d2012-05-22 17:01:35 +000053
54 FileID createInMemoryFile(StringRef Name, StringRef Content) {
Rafael Espindolad87f8d72014-08-27 20:03:29 +000055 std::unique_ptr<llvm::MemoryBuffer> Source =
56 llvm::MemoryBuffer::getMemBuffer(Content);
Benjamin Kramera25dcfd2015-10-05 13:55:14 +000057 InMemoryFileSystem->addFile(Name, 0, std::move(Source));
58
59 const FileEntry *Entry = Files.getFile(Name);
Craig Topper416fa342014-06-08 08:38:12 +000060 assert(Entry != nullptr);
Manuel Klimek78d084d2012-05-22 17:01:35 +000061 return Sources.createFileID(Entry, SourceLocation(), SrcMgr::C_User);
62 }
63
Rafael Espindola8b960942013-06-26 21:02:22 +000064 // FIXME: this code is mostly a duplicate of
65 // unittests/Tooling/RefactoringTest.cpp. Figure out a way to share it.
Manuel Klimek78d084d2012-05-22 17:01:35 +000066 FileID createOnDiskFile(StringRef Name, StringRef Content) {
Rafael Espindola8b960942013-06-26 21:02:22 +000067 SmallString<1024> Path;
68 int FD;
Rafael Espindolac0809172014-06-12 14:02:15 +000069 std::error_code EC = llvm::sys::fs::createTemporaryFile(Name, "", FD, Path);
Rafael Espindola8b960942013-06-26 21:02:22 +000070 assert(!EC);
71 (void)EC;
72
73 llvm::raw_fd_ostream OutStream(FD, true);
Manuel Klimek78d084d2012-05-22 17:01:35 +000074 OutStream << Content;
75 OutStream.close();
76 const FileEntry *File = Files.getFile(Path);
Craig Topper416fa342014-06-08 08:38:12 +000077 assert(File != nullptr);
Rafael Espindola8b960942013-06-26 21:02:22 +000078
David Blaikie13156b62014-11-19 03:06:06 +000079 StringRef Found =
80 TemporaryFiles.insert(std::make_pair(Name, Path.str())).first->second;
Rafael Espindola8b960942013-06-26 21:02:22 +000081 assert(Found == Path);
82 (void)Found;
Manuel Klimek78d084d2012-05-22 17:01:35 +000083 return Sources.createFileID(File, SourceLocation(), SrcMgr::C_User);
84 }
85
86 SourceLocation getLocation(FileID ID, unsigned Line, unsigned Column) {
87 SourceLocation Result = Sources.translateFileLineCol(
88 Sources.getFileEntryForID(ID), Line, Column);
89 assert(Result.isValid());
90 return Result;
91 }
92
93 std::string getRewrittenText(FileID ID) {
94 std::string Result;
95 llvm::raw_string_ostream OS(Result);
96 Rewrite.getEditBuffer(ID).write(OS);
Manuel Klimekee56b542012-06-05 20:16:30 +000097 OS.flush();
Manuel Klimek78d084d2012-05-22 17:01:35 +000098 return Result;
99 }
100
101 std::string getFileContentFromDisk(StringRef Name) {
Rafael Espindola8b960942013-06-26 21:02:22 +0000102 std::string Path = TemporaryFiles.lookup(Name);
103 assert(!Path.empty());
Manuel Klimek78d084d2012-05-22 17:01:35 +0000104 // We need to read directly from the FileManager without relaying through
105 // a FileEntry, as otherwise we'd read through an already opened file
106 // descriptor, which might not see the changes made.
107 // FIXME: Figure out whether there is a way to get the SourceManger to
108 // reopen the file.
Benjamin Kramera8857962014-10-26 22:44:13 +0000109 auto FileBuffer = Files.getBufferForFile(Path);
110 return (*FileBuffer)->getBuffer();
Manuel Klimek78d084d2012-05-22 17:01:35 +0000111 }
112
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000113 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
Manuel Klimek78d084d2012-05-22 17:01:35 +0000114 DiagnosticsEngine Diagnostics;
115 TextDiagnosticPrinter DiagnosticPrinter;
Jonas Devliegherefc514902018-10-10 13:27:25 +0000116 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem;
117 IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem;
Manuel Klimek78d084d2012-05-22 17:01:35 +0000118 FileManager Files;
119 SourceManager Sources;
120 LangOptions Options;
121 Rewriter Rewrite;
122
Manuel Klimek0a8b9cd2012-06-06 21:28:13 +0000123 // Will be set once on disk files are generated.
Rafael Espindola8b960942013-06-26 21:02:22 +0000124 llvm::StringMap<std::string> TemporaryFiles;
Manuel Klimek78d084d2012-05-22 17:01:35 +0000125};
126
127} // end namespace clang
128
129#endif