|
12 | 12 |
|
13 | 13 | #include "swift/Basic/SourceLoc.h"
|
14 | 14 | #include "swift/Basic/SourceManager.h"
|
| 15 | +#include "llvm/Support/FileSystem.h" |
15 | 16 | #include "llvm/Support/MemoryBuffer.h"
|
16 | 17 | #include "llvm/Support/PrettyStackTrace.h"
|
17 | 18 | #include "llvm/Support/raw_ostream.h"
|
| 19 | +#include "llvm/Support/Signals.h" |
18 | 20 |
|
19 | 21 | using namespace swift;
|
20 | 22 |
|
@@ -43,13 +45,14 @@ SourceLoc SourceManager::getIDEInspectionTargetLoc() const {
|
43 | 45 | .getAdvancedLoc(IDEInspectionTargetOffset);
|
44 | 46 | }
|
45 | 47 |
|
46 |
| -StringRef SourceManager::getDisplayNameForLoc(SourceLoc Loc) const { |
| 48 | +StringRef SourceManager::getDisplayNameForLoc(SourceLoc Loc, bool ForceGeneratedSourceToDisk) const { |
47 | 49 | // Respect #line first
|
48 | 50 | if (auto VFile = getVirtualFile(Loc))
|
49 | 51 | return VFile->Name;
|
50 | 52 |
|
51 | 53 | // Next, try the stat cache
|
52 |
| - auto Ident = getIdentifierForBuffer(findBufferContainingLoc(Loc)); |
| 54 | + auto Ident = getIdentifierForBuffer( |
| 55 | + findBufferContainingLoc(Loc), ForceGeneratedSourceToDisk); |
53 | 56 | auto found = StatusCache.find(Ident);
|
54 | 57 | if (found != StatusCache.end()) {
|
55 | 58 | return found->second.getName();
|
@@ -184,9 +187,53 @@ SourceManager::getIDForBufferIdentifier(StringRef BufIdentifier) const {
|
184 | 187 | return It->second;
|
185 | 188 | }
|
186 | 189 |
|
187 |
| -StringRef SourceManager::getIdentifierForBuffer(unsigned bufferID) const { |
| 190 | +/// Dump the contents of the given memory buffer to a file, returning the |
| 191 | +/// name of that file (when successful) and \c None otherwise. |
| 192 | +static Optional<std::string> |
| 193 | +dumpBufferToFile(const llvm::MemoryBuffer *buffer) { |
| 194 | + // Create file in the system temporary directory. |
| 195 | + SmallString<128> tempFileModel; |
| 196 | + llvm::sys::path::system_temp_directory(true, tempFileModel); |
| 197 | + llvm::sys::path::append( |
| 198 | + tempFileModel, "swift-generated-sources-%%%%%%.swift"); |
| 199 | + |
| 200 | + // Open up a unique file. |
| 201 | + int tempFD = 0; |
| 202 | + SmallString<128> tempFileName; |
| 203 | + if (llvm::sys::fs::createUniqueFile(tempFileModel, tempFD, tempFileName)) |
| 204 | + return None; |
| 205 | + |
| 206 | + // Dump the contents there. |
| 207 | + llvm::raw_fd_ostream out(tempFD, true); |
| 208 | + out << buffer->getBuffer(); |
| 209 | + out.flush(); |
| 210 | + |
| 211 | + llvm::sys::DontRemoveFileOnSignal(tempFileName); |
| 212 | + return tempFileName.str().str(); |
| 213 | +} |
| 214 | + |
| 215 | +StringRef SourceManager::getIdentifierForBuffer( |
| 216 | + unsigned bufferID, bool ForceGeneratedSourceToDisk |
| 217 | +) const { |
188 | 218 | auto *buffer = LLVMSourceMgr.getMemoryBuffer(bufferID);
|
189 | 219 | assert(buffer && "invalid buffer ID");
|
| 220 | + |
| 221 | + // If this is generated source code, and we're supposed to force it to disk |
| 222 | + // so external clients can see it, do so now. |
| 223 | + if (ForceGeneratedSourceToDisk) { |
| 224 | + if (auto generatedInfo = getGeneratedSourceInfo(bufferID)) { |
| 225 | + if (generatedInfo->onDiskBufferCopyFileName.empty()) { |
| 226 | + if (auto newFileNameOpt = dumpBufferToFile(buffer)) { |
| 227 | + generatedInfo->onDiskBufferCopyFileName = |
| 228 | + strdup(newFileNameOpt->c_str()); |
| 229 | + } |
| 230 | + } |
| 231 | + |
| 232 | + if (!generatedInfo->onDiskBufferCopyFileName.empty()) |
| 233 | + return generatedInfo->onDiskBufferCopyFileName; |
| 234 | + } |
| 235 | + } |
| 236 | + |
190 | 237 | return buffer->getBufferIdentifier();
|
191 | 238 | }
|
192 | 239 |
|
|
0 commit comments