• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===--- 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"
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"
27 
28 namespace 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.
35 class RewriterTestContext {
36  public:
RewriterTestContext()37   RewriterTestContext()
38       : DiagOpts(new DiagnosticOptions()),
39         Diagnostics(IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
40                     &*DiagOpts),
41         DiagnosticPrinter(llvm::outs(), &*DiagOpts),
42         Files((FileSystemOptions())),
43         Sources(Diagnostics, Files),
44         Rewrite(Sources, Options) {
45     Diagnostics.setClient(&DiagnosticPrinter, false);
46   }
47 
~RewriterTestContext()48   ~RewriterTestContext() {}
49 
createInMemoryFile(StringRef Name,StringRef Content)50   FileID createInMemoryFile(StringRef Name, StringRef Content) {
51     llvm::MemoryBuffer *Source = llvm::MemoryBuffer::getMemBuffer(Content);
52     const FileEntry *Entry =
53       Files.getVirtualFile(Name, Source->getBufferSize(), 0);
54     Sources.overrideFileContents(Entry, Source);
55     assert(Entry != nullptr);
56     return Sources.createFileID(Entry, SourceLocation(), SrcMgr::C_User);
57   }
58 
59   // FIXME: this code is mostly a duplicate of
60   // unittests/Tooling/RefactoringTest.cpp. Figure out a way to share it.
createOnDiskFile(StringRef Name,StringRef Content)61   FileID createOnDiskFile(StringRef Name, StringRef Content) {
62     SmallString<1024> Path;
63     int FD;
64     std::error_code EC = llvm::sys::fs::createTemporaryFile(Name, "", FD, Path);
65     assert(!EC);
66     (void)EC;
67 
68     llvm::raw_fd_ostream OutStream(FD, true);
69     OutStream << Content;
70     OutStream.close();
71     const FileEntry *File = Files.getFile(Path);
72     assert(File != nullptr);
73 
74     StringRef Found = TemporaryFiles.GetOrCreateValue(Name, Path.str()).second;
75     assert(Found == Path);
76     (void)Found;
77     return Sources.createFileID(File, SourceLocation(), SrcMgr::C_User);
78   }
79 
getLocation(FileID ID,unsigned Line,unsigned Column)80   SourceLocation getLocation(FileID ID, unsigned Line, unsigned Column) {
81     SourceLocation Result = Sources.translateFileLineCol(
82         Sources.getFileEntryForID(ID), Line, Column);
83     assert(Result.isValid());
84     return Result;
85   }
86 
getRewrittenText(FileID ID)87   std::string getRewrittenText(FileID ID) {
88     std::string Result;
89     llvm::raw_string_ostream OS(Result);
90     Rewrite.getEditBuffer(ID).write(OS);
91     OS.flush();
92     return Result;
93   }
94 
getFileContentFromDisk(StringRef Name)95   std::string getFileContentFromDisk(StringRef Name) {
96     std::string Path = TemporaryFiles.lookup(Name);
97     assert(!Path.empty());
98     // We need to read directly from the FileManager without relaying through
99     // a FileEntry, as otherwise we'd read through an already opened file
100     // descriptor, which might not see the changes made.
101     // FIXME: Figure out whether there is a way to get the SourceManger to
102     // reopen the file.
103     std::unique_ptr<const llvm::MemoryBuffer> FileBuffer(
104         Files.getBufferForFile(Path, nullptr));
105     return FileBuffer->getBuffer();
106   }
107 
108   IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
109   DiagnosticsEngine Diagnostics;
110   TextDiagnosticPrinter DiagnosticPrinter;
111   FileManager Files;
112   SourceManager Sources;
113   LangOptions Options;
114   Rewriter Rewrite;
115 
116   // Will be set once on disk files are generated.
117   llvm::StringMap<std::string> TemporaryFiles;
118 };
119 
120 } // end namespace clang
121 
122 #endif
123