xref: /aosp_15_r20/external/clang/unittests/Tooling/RewriterTestContext.h (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li //===--- RewriterTestContext.h ----------------------------------*- C++ -*-===//
2*67e74705SXin Li //
3*67e74705SXin Li //                     The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li //
10*67e74705SXin Li //  This file defines a utility class for Rewriter related tests.
11*67e74705SXin Li //
12*67e74705SXin Li //===----------------------------------------------------------------------===//
13*67e74705SXin Li 
14*67e74705SXin Li #ifndef LLVM_CLANG_UNITTESTS_TOOLING_REWRITERTESTCONTEXT_H
15*67e74705SXin Li #define LLVM_CLANG_UNITTESTS_TOOLING_REWRITERTESTCONTEXT_H
16*67e74705SXin Li 
17*67e74705SXin Li #include "clang/Basic/Diagnostic.h"
18*67e74705SXin Li #include "clang/Basic/DiagnosticOptions.h"
19*67e74705SXin Li #include "clang/Basic/FileManager.h"
20*67e74705SXin Li #include "clang/Basic/LangOptions.h"
21*67e74705SXin Li #include "clang/Basic/SourceManager.h"
22*67e74705SXin Li #include "clang/Frontend/TextDiagnosticPrinter.h"
23*67e74705SXin Li #include "clang/Rewrite/Core/Rewriter.h"
24*67e74705SXin Li #include "llvm/Support/FileSystem.h"
25*67e74705SXin Li #include "llvm/Support/Path.h"
26*67e74705SXin Li #include "llvm/Support/raw_ostream.h"
27*67e74705SXin Li 
28*67e74705SXin Li namespace clang {
29*67e74705SXin Li 
30*67e74705SXin Li /// \brief A class that sets up a ready to use Rewriter.
31*67e74705SXin Li ///
32*67e74705SXin Li /// Useful in unit tests that need a Rewriter. Creates all dependencies
33*67e74705SXin Li /// of a Rewriter with default values for testing and provides convenience
34*67e74705SXin Li /// methods, which help with writing tests that change files.
35*67e74705SXin Li class RewriterTestContext {
36*67e74705SXin Li  public:
RewriterTestContext()37*67e74705SXin Li    RewriterTestContext()
38*67e74705SXin Li        : DiagOpts(new DiagnosticOptions()),
39*67e74705SXin Li          Diagnostics(IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
40*67e74705SXin Li                      &*DiagOpts),
41*67e74705SXin Li          DiagnosticPrinter(llvm::outs(), &*DiagOpts),
42*67e74705SXin Li          InMemoryFileSystem(new vfs::InMemoryFileSystem),
43*67e74705SXin Li          OverlayFileSystem(
44*67e74705SXin Li              new vfs::OverlayFileSystem(vfs::getRealFileSystem())),
45*67e74705SXin Li          Files(FileSystemOptions(), OverlayFileSystem),
46*67e74705SXin Li          Sources(Diagnostics, Files), Rewrite(Sources, Options) {
47*67e74705SXin Li     Diagnostics.setClient(&DiagnosticPrinter, false);
48*67e74705SXin Li     // FIXME: To make these tests truly in-memory, we need to overlay the
49*67e74705SXin Li     // builtin headers.
50*67e74705SXin Li     OverlayFileSystem->pushOverlay(InMemoryFileSystem);
51*67e74705SXin Li   }
52*67e74705SXin Li 
~RewriterTestContext()53*67e74705SXin Li   ~RewriterTestContext() {}
54*67e74705SXin Li 
createInMemoryFile(StringRef Name,StringRef Content)55*67e74705SXin Li   FileID createInMemoryFile(StringRef Name, StringRef Content) {
56*67e74705SXin Li     std::unique_ptr<llvm::MemoryBuffer> Source =
57*67e74705SXin Li         llvm::MemoryBuffer::getMemBuffer(Content);
58*67e74705SXin Li     InMemoryFileSystem->addFile(Name, 0, std::move(Source));
59*67e74705SXin Li 
60*67e74705SXin Li     const FileEntry *Entry = Files.getFile(Name);
61*67e74705SXin Li     assert(Entry != nullptr);
62*67e74705SXin Li     return Sources.createFileID(Entry, SourceLocation(), SrcMgr::C_User);
63*67e74705SXin Li   }
64*67e74705SXin Li 
65*67e74705SXin Li   // FIXME: this code is mostly a duplicate of
66*67e74705SXin Li   // unittests/Tooling/RefactoringTest.cpp. Figure out a way to share it.
createOnDiskFile(StringRef Name,StringRef Content)67*67e74705SXin Li   FileID createOnDiskFile(StringRef Name, StringRef Content) {
68*67e74705SXin Li     SmallString<1024> Path;
69*67e74705SXin Li     int FD;
70*67e74705SXin Li     std::error_code EC = llvm::sys::fs::createTemporaryFile(Name, "", FD, Path);
71*67e74705SXin Li     assert(!EC);
72*67e74705SXin Li     (void)EC;
73*67e74705SXin Li 
74*67e74705SXin Li     llvm::raw_fd_ostream OutStream(FD, true);
75*67e74705SXin Li     OutStream << Content;
76*67e74705SXin Li     OutStream.close();
77*67e74705SXin Li     const FileEntry *File = Files.getFile(Path);
78*67e74705SXin Li     assert(File != nullptr);
79*67e74705SXin Li 
80*67e74705SXin Li     StringRef Found =
81*67e74705SXin Li         TemporaryFiles.insert(std::make_pair(Name, Path.str())).first->second;
82*67e74705SXin Li     assert(Found == Path);
83*67e74705SXin Li     (void)Found;
84*67e74705SXin Li     return Sources.createFileID(File, SourceLocation(), SrcMgr::C_User);
85*67e74705SXin Li   }
86*67e74705SXin Li 
getLocation(FileID ID,unsigned Line,unsigned Column)87*67e74705SXin Li   SourceLocation getLocation(FileID ID, unsigned Line, unsigned Column) {
88*67e74705SXin Li     SourceLocation Result = Sources.translateFileLineCol(
89*67e74705SXin Li         Sources.getFileEntryForID(ID), Line, Column);
90*67e74705SXin Li     assert(Result.isValid());
91*67e74705SXin Li     return Result;
92*67e74705SXin Li   }
93*67e74705SXin Li 
getRewrittenText(FileID ID)94*67e74705SXin Li   std::string getRewrittenText(FileID ID) {
95*67e74705SXin Li     std::string Result;
96*67e74705SXin Li     llvm::raw_string_ostream OS(Result);
97*67e74705SXin Li     Rewrite.getEditBuffer(ID).write(OS);
98*67e74705SXin Li     OS.flush();
99*67e74705SXin Li     return Result;
100*67e74705SXin Li   }
101*67e74705SXin Li 
getFileContentFromDisk(StringRef Name)102*67e74705SXin Li   std::string getFileContentFromDisk(StringRef Name) {
103*67e74705SXin Li     std::string Path = TemporaryFiles.lookup(Name);
104*67e74705SXin Li     assert(!Path.empty());
105*67e74705SXin Li     // We need to read directly from the FileManager without relaying through
106*67e74705SXin Li     // a FileEntry, as otherwise we'd read through an already opened file
107*67e74705SXin Li     // descriptor, which might not see the changes made.
108*67e74705SXin Li     // FIXME: Figure out whether there is a way to get the SourceManger to
109*67e74705SXin Li     // reopen the file.
110*67e74705SXin Li     auto FileBuffer = Files.getBufferForFile(Path);
111*67e74705SXin Li     return (*FileBuffer)->getBuffer();
112*67e74705SXin Li   }
113*67e74705SXin Li 
114*67e74705SXin Li   IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
115*67e74705SXin Li   DiagnosticsEngine Diagnostics;
116*67e74705SXin Li   TextDiagnosticPrinter DiagnosticPrinter;
117*67e74705SXin Li   IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem;
118*67e74705SXin Li   IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem;
119*67e74705SXin Li   FileManager Files;
120*67e74705SXin Li   SourceManager Sources;
121*67e74705SXin Li   LangOptions Options;
122*67e74705SXin Li   Rewriter Rewrite;
123*67e74705SXin Li 
124*67e74705SXin Li   // Will be set once on disk files are generated.
125*67e74705SXin Li   llvm::StringMap<std::string> TemporaryFiles;
126*67e74705SXin Li };
127*67e74705SXin Li 
128*67e74705SXin Li } // end namespace clang
129*67e74705SXin Li 
130*67e74705SXin Li #endif
131