Skip to content

Commit 5f129af

Browse files
DougGregoradrian-prantl
authored andcommitted
Introduce infrastructure to dump generated source buffers into temporary files
1 parent 3cc5628 commit 5f129af

File tree

2 files changed

+68
-5
lines changed

2 files changed

+68
-5
lines changed

include/swift/Basic/SourceManager.h

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ class GeneratedSourceInfo {
7272

7373
/// The custom attribute for an attached macro.
7474
CustomAttr *attachedMacroCustomAttr = nullptr;
75+
76+
/// The name of the source file on disk that was created to hold the
77+
/// contents of this file for external clients.
78+
StringRef onDiskBufferCopyFileName = StringRef();
7579
};
7680

7781
/// This class manages and owns source buffers.
@@ -253,11 +257,18 @@ class SourceManager {
253257
///
254258
/// \p BufferID must be a valid buffer ID.
255259
///
260+
/// \p ForceGeneratedSourceToDisk can be set to true to create a temporary
261+
/// file on-disk for buffers containing generated source code, returning the
262+
/// name of that temporary file.
263+
///
256264
/// This should not be used for displaying information about the \e contents
257265
/// of a buffer, since lines within the buffer may be marked as coming from
258266
/// other files using \c #sourceLocation. Use #getDisplayNameForLoc instead
259267
/// in that case.
260-
StringRef getIdentifierForBuffer(unsigned BufferID) const;
268+
StringRef getIdentifierForBuffer(
269+
unsigned BufferID,
270+
bool ForceGeneratedSourceToDisk = false
271+
) const;
261272

262273
/// Returns a SourceRange covering the entire specified buffer.
263274
///
@@ -289,10 +300,15 @@ class SourceManager {
289300
/// Returns a buffer identifier suitable for display to the user containing
290301
/// the given source location.
291302
///
303+
/// \p ForceGeneratedSourceToDisk can be set to true to create a temporary
304+
/// file on-disk for buffers containing generated source code, returning the
305+
/// name of that temporary file.
306+
///
292307
/// This respects \c #sourceLocation directives and the 'use-external-names'
293308
/// directive in VFS overlay files. If you need an on-disk file name, use
294309
/// #getIdentifierForBuffer instead.
295-
StringRef getDisplayNameForLoc(SourceLoc Loc) const;
310+
StringRef getDisplayNameForLoc(
311+
SourceLoc Loc, bool ForceGeneratedSourceToDisk = false) const;
296312

297313
/// Returns the line and column represented by the given source location.
298314
///

lib/Basic/SourceLoc.cpp

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212

1313
#include "swift/Basic/SourceLoc.h"
1414
#include "swift/Basic/SourceManager.h"
15+
#include "llvm/Support/FileSystem.h"
1516
#include "llvm/Support/MemoryBuffer.h"
1617
#include "llvm/Support/PrettyStackTrace.h"
1718
#include "llvm/Support/raw_ostream.h"
19+
#include "llvm/Support/Signals.h"
1820

1921
using namespace swift;
2022

@@ -43,13 +45,14 @@ SourceLoc SourceManager::getIDEInspectionTargetLoc() const {
4345
.getAdvancedLoc(IDEInspectionTargetOffset);
4446
}
4547

46-
StringRef SourceManager::getDisplayNameForLoc(SourceLoc Loc) const {
48+
StringRef SourceManager::getDisplayNameForLoc(SourceLoc Loc, bool ForceGeneratedSourceToDisk) const {
4749
// Respect #line first
4850
if (auto VFile = getVirtualFile(Loc))
4951
return VFile->Name;
5052

5153
// Next, try the stat cache
52-
auto Ident = getIdentifierForBuffer(findBufferContainingLoc(Loc));
54+
auto Ident = getIdentifierForBuffer(
55+
findBufferContainingLoc(Loc), ForceGeneratedSourceToDisk);
5356
auto found = StatusCache.find(Ident);
5457
if (found != StatusCache.end()) {
5558
return found->second.getName();
@@ -184,9 +187,53 @@ SourceManager::getIDForBufferIdentifier(StringRef BufIdentifier) const {
184187
return It->second;
185188
}
186189

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 {
188218
auto *buffer = LLVMSourceMgr.getMemoryBuffer(bufferID);
189219
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+
190237
return buffer->getBufferIdentifier();
191238
}
192239

0 commit comments

Comments
 (0)