14 #include "llvm/Support/FileSystem.h"
15 #include "llvm/Support/MemoryBuffer.h"
16 #include "llvm/Support/Path.h"
17 #include "llvm/Support/raw_ostream.h"
20 using namespace clang;
21 using namespace arcmt;
33 I = FromToMappings.begin(),
E = FromToMappings.end();
I !=
E; ++
I)
34 resetTarget(
I->second);
35 FromToMappings.clear();
36 assert(ToFromMappings.empty());
37 if (!outputDir.empty()) {
38 std::string infoFile = getRemapInfoFile(outputDir);
39 llvm::sys::fs::remove(infoFile);
43 std::string FileRemapper::getRemapInfoFile(StringRef outputDir) {
44 assert(!outputDir.empty());
46 llvm::sys::path::append(InfoFile,
"remap");
47 return InfoFile.str();
51 bool ignoreIfFilesChanged) {
52 std::string infoFile = getRemapInfoFile(outputDir);
53 return initFromFile(infoFile, Diag, ignoreIfFilesChanged);
57 bool ignoreIfFilesChanged) {
58 assert(FromToMappings.empty() &&
59 "initFromDisk should be called before any remap calls");
60 std::string infoFile = filePath;
61 if (!llvm::sys::fs::exists(infoFile))
64 std::vector<std::pair<const FileEntry *, const FileEntry *> > pairs;
66 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileBuf =
67 llvm::MemoryBuffer::getFile(infoFile.c_str());
69 return report(
"Error opening file: " + infoFile, Diag);
72 fileBuf.get()->getBuffer().split(lines,
"\n");
74 for (
unsigned idx = 0; idx+3 <= lines.size(); idx += 3) {
75 StringRef fromFilename = lines[idx];
76 unsigned long long timeModified;
77 if (lines[idx+1].getAsInteger(10, timeModified))
78 return report(
"Invalid file data: '" + lines[idx+1] +
"' not a number",
80 StringRef toFilename = lines[idx+2];
82 const FileEntry *origFE = FileMgr->getFile(fromFilename);
84 if (ignoreIfFilesChanged)
86 return report(
"File does not exist: " + fromFilename, Diag);
88 const FileEntry *newFE = FileMgr->getFile(toFilename);
90 if (ignoreIfFilesChanged)
92 return report(
"File does not exist: " + toFilename, Diag);
96 if (ignoreIfFilesChanged)
98 return report(
"File was modified: " + fromFilename, Diag);
101 pairs.push_back(std::make_pair(origFE, newFE));
104 for (
unsigned i = 0, e = pairs.size(); i != e; ++i)
105 remap(pairs[i].first, pairs[i].second);
111 using namespace llvm::sys;
113 if (fs::create_directory(outputDir))
114 return report(
"Could not create directory: " + outputDir, Diag);
116 std::string infoFile = getRemapInfoFile(outputDir);
121 using namespace llvm::sys;
124 std::string infoFile = outputPath;
125 llvm::raw_fd_ostream infoOut(infoFile, EC, llvm::sys::fs::F_None);
127 return report(EC.message(),
Diag);
130 I = FromToMappings.begin(),
E = FromToMappings.end();
I !=
E; ++
I) {
134 fs::make_absolute(origPath);
135 infoOut << origPath <<
'\n';
140 fs::make_absolute(newPath);
141 infoOut << newPath <<
'\n';
146 if (fs::createTemporaryFile(path::filename(origFE->
getName()),
147 path::extension(origFE->
getName()).drop_front(), fd,
149 return report(
"Could not create file: " + tempPath.str(),
Diag);
151 llvm::raw_fd_ostream newOut(fd,
true);
152 llvm::MemoryBuffer *mem =
I->second.get<llvm::MemoryBuffer *>();
153 newOut.write(mem->getBufferStart(), mem->getBufferSize());
156 const FileEntry *newE = FileMgr->getFile(tempPath);
158 infoOut << newE->
getName() <<
'\n';
167 StringRef outputDir) {
168 using namespace llvm::sys;
171 I = FromToMappings.begin(),
E = FromToMappings.end();
I !=
E; ++
I) {
173 assert(
I->second.is<llvm::MemoryBuffer *>());
174 if (!fs::exists(origFE->
getName()))
175 return report(StringRef(
"File does not exist: ") + origFE->
getName(),
179 llvm::raw_fd_ostream Out(origFE->
getName(), EC, llvm::sys::fs::F_None);
181 return report(EC.message(),
Diag);
183 llvm::MemoryBuffer *mem =
I->second.get<llvm::MemoryBuffer *>();
184 Out.write(mem->getBufferStart(), mem->getBufferSize());
193 for (MappingsTy::const_iterator
194 I = FromToMappings.begin(),
E = FromToMappings.end();
I !=
E; ++
I) {
198 llvm::MemoryBuffer *mem =
I->second.get<llvm::MemoryBuffer *>();
207 std::unique_ptr<llvm::MemoryBuffer> memBuf) {
208 remap(getOriginalFile(filePath), std::move(memBuf));
212 std::unique_ptr<llvm::MemoryBuffer> memBuf) {
214 Target &targ = FromToMappings[file];
216 targ = memBuf.release();
220 assert(file && newfile);
221 Target &targ = FromToMappings[file];
224 ToFromMappings[newfile] = file;
227 const FileEntry *FileRemapper::getOriginalFile(StringRef filePath) {
228 const FileEntry *file = FileMgr->getFile(filePath);
232 I = ToFromMappings.find(file);
233 if (I != ToFromMappings.end()) {
235 assert(FromToMappings.find(file) != FromToMappings.end() &&
236 "Original file not in mappings!");
241 void FileRemapper::resetTarget(Target &targ) {
245 if (llvm::MemoryBuffer *oldmem = targ.dyn_cast<llvm::MemoryBuffer *>()) {
249 ToFromMappings.erase(toFE);
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
Implements support for file system lookup, file system caching, and directory search management...
Defines the clang::FileManager interface and associated types.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
PreprocessorOptions - This class is used for passing the various options used in preprocessor initial...
void addRemappedFile(StringRef From, StringRef To)
void remap(StringRef filePath, std::unique_ptr< llvm::MemoryBuffer > memBuf)
Concrete class used by the front-end to report problems and issues.
bool RetainRemappedFileBuffers
Whether the compiler instance should retain (i.e., not free) the buffers associated with remapped fil...
detail::InMemoryDirectory::const_iterator I
bool flushToFile(StringRef outputPath, DiagnosticsEngine &Diag)
void applyMappings(PreprocessorOptions &PPOpts) const
bool initFromFile(StringRef filePath, DiagnosticsEngine &Diag, bool ignoreIfFilesChanged)
bool overwriteOriginal(DiagnosticsEngine &Diag, StringRef outputDir=StringRef())
const char * getName() const
const TemplateArgument * iterator
bool flushToDisk(StringRef outputDir, DiagnosticsEngine &Diag)
Cached information about one file (either on disk or in the virtual file system). ...
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
detail::InMemoryDirectory::const_iterator E
Defines the Diagnostic-related interfaces.
time_t getModificationTime() const
Keeps track of options that affect how file operations are performed.
bool initFromDisk(StringRef outputDir, DiagnosticsEngine &Diag, bool ignoreIfFilesChanged)
void clear(StringRef outputDir=StringRef())