1bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek//===--- RewriterTestContext.h ----------------------------------*- C++ -*-===//
2bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek//
3bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek//                     The LLVM Compiler Infrastructure
4bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek//
5bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek// This file is distributed under the University of Illinois Open Source
6bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek// License. See LICENSE.TXT for details.
7bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek//
8bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek//===----------------------------------------------------------------------===//
9bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek//
10bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek//  This file defines a utility class for Rewriter related tests.
11bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek//
12bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek//===----------------------------------------------------------------------===//
13bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek
14bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek#ifndef LLVM_CLANG_REWRITER_TEST_CONTEXT_H
15bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek#define LLVM_CLANG_REWRITER_TEST_CONTEXT_H
16bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek
17bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek#include "clang/Basic/Diagnostic.h"
1899eb4a7920667d23a89df8fcc6429d12b36e4d57Douglas Gregor#include "clang/Basic/DiagnosticOptions.h"
19bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek#include "clang/Basic/FileManager.h"
20bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek#include "clang/Basic/LangOptions.h"
21bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek#include "clang/Basic/SourceManager.h"
22bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek#include "clang/Frontend/TextDiagnosticPrinter.h"
23305c613af6cfc40e519c75d9d2c84c6fa9a841c0Ted Kremenek#include "clang/Rewrite/Core/Rewriter.h"
247b699ac3ac8ce48cf9e9387f6b6830f3a8d409d5Manuel Klimek#include "llvm/Support/FileSystem.h"
25bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek#include "llvm/Support/Path.h"
26bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek#include "llvm/Support/raw_ostream.h"
27bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek
28bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimeknamespace clang {
29bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek
30bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek/// \brief A class that sets up a ready to use Rewriter.
31bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek///
32bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek/// Useful in unit tests that need a Rewriter. Creates all dependencies
33bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek/// of a Rewriter with default values for testing and provides convenience
34bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek/// methods, which help with writing tests that change files.
35bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimekclass RewriterTestContext {
36bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek public:
37bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  RewriterTestContext()
3899eb4a7920667d23a89df8fcc6429d12b36e4d57Douglas Gregor      : DiagOpts(new DiagnosticOptions()),
39cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko        Diagnostics(IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
4099eb4a7920667d23a89df8fcc6429d12b36e4d57Douglas Gregor                    &*DiagOpts),
4199eb4a7920667d23a89df8fcc6429d12b36e4d57Douglas Gregor        DiagnosticPrinter(llvm::outs(), &*DiagOpts),
42bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek        Files((FileSystemOptions())),
43bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek        Sources(Diagnostics, Files),
44bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek        Rewrite(Sources, Options) {
45bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    Diagnostics.setClient(&DiagnosticPrinter, false);
46bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  }
47bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek
485bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola  ~RewriterTestContext() {}
49bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek
50bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  FileID createInMemoryFile(StringRef Name, StringRef Content) {
51bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    const llvm::MemoryBuffer *Source =
52bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek      llvm::MemoryBuffer::getMemBuffer(Content);
53bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    const FileEntry *Entry =
54bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek      Files.getVirtualFile(Name, Source->getBufferSize(), 0);
55bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    Sources.overrideFileContents(Entry, Source, true);
56bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    assert(Entry != NULL);
57bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    return Sources.createFileID(Entry, SourceLocation(), SrcMgr::C_User);
58bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  }
59bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek
605bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola  // FIXME: this code is mostly a duplicate of
615bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola  // unittests/Tooling/RefactoringTest.cpp. Figure out a way to share it.
62bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  FileID createOnDiskFile(StringRef Name, StringRef Content) {
635bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola    SmallString<1024> Path;
645bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola    int FD;
655bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola    llvm::error_code EC =
661ec4a86a867fc04f35d13bc9e33b04cf2171fe41Rafael Espindola        llvm::sys::fs::createTemporaryFile(Name, "", FD, Path);
675bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola    assert(!EC);
685bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola    (void)EC;
695bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola
705bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola    llvm::raw_fd_ostream OutStream(FD, true);
71bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    OutStream << Content;
72bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    OutStream.close();
73bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    const FileEntry *File = Files.getFile(Path);
74bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    assert(File != NULL);
755bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola
765bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola    StringRef Found = TemporaryFiles.GetOrCreateValue(Name, Path.str()).second;
775bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola    assert(Found == Path);
785bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola    (void)Found;
79bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    return Sources.createFileID(File, SourceLocation(), SrcMgr::C_User);
80bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  }
81bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek
82bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  SourceLocation getLocation(FileID ID, unsigned Line, unsigned Column) {
83bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    SourceLocation Result = Sources.translateFileLineCol(
84bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek        Sources.getFileEntryForID(ID), Line, Column);
85bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    assert(Result.isValid());
86bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    return Result;
87bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  }
88bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek
89bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  std::string getRewrittenText(FileID ID) {
90bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    std::string Result;
91bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    llvm::raw_string_ostream OS(Result);
92bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    Rewrite.getEditBuffer(ID).write(OS);
93d6f6569bf693da3f8efd8ce7ae93fbbfccf09753Manuel Klimek    OS.flush();
94bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    return Result;
95bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  }
96bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek
97bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  std::string getFileContentFromDisk(StringRef Name) {
985bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola    std::string Path = TemporaryFiles.lookup(Name);
995bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola    assert(!Path.empty());
100bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    // We need to read directly from the FileManager without relaying through
101bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    // a FileEntry, as otherwise we'd read through an already opened file
102bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    // descriptor, which might not see the changes made.
103bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    // FIXME: Figure out whether there is a way to get the SourceManger to
104bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    // reopen the file.
105bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    return Files.getBufferForFile(Path, NULL)->getBuffer();
106bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  }
107bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek
108cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
109bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  DiagnosticsEngine Diagnostics;
110bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  TextDiagnosticPrinter DiagnosticPrinter;
111bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  FileManager Files;
112bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  SourceManager Sources;
113bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  LangOptions Options;
114bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  Rewriter Rewrite;
115bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek
1167b699ac3ac8ce48cf9e9387f6b6830f3a8d409d5Manuel Klimek  // Will be set once on disk files are generated.
1175bb5f6a84ef98e410fdc89d82f4b7565fb5616e5Rafael Espindola  llvm::StringMap<std::string> TemporaryFiles;
118bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek};
119bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek
120bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek} // end namespace clang
121bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek
122bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek#endif
123