aboutsummaryrefslogtreecommitdiff
path: root/lib/Basic/SourceManager.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-09-22 21:11:38 +0000
committerDouglas Gregor <dgregor@apple.com>2009-09-22 21:11:38 +0000
commitb657f115c3b4e262e72906a28cbcf3eaccd9460c (patch)
tree95502c386d41a13dd1c04b189247446b9fb8d18e /lib/Basic/SourceManager.cpp
parentadd28829c7a8d3c5da9ae140f18d3c9ad2d8b599 (diff)
Replace the -code-completion-dump option with
-code-completion-at=filename:line:column which performs code completion at the specified location by truncating the file at that position and enabling code completion. This approach makes it possible to run multiple tests from a single test file, and gives a more natural command-line interface. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82571 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Basic/SourceManager.cpp')
-rw-r--r--lib/Basic/SourceManager.cpp81
1 files changed, 79 insertions, 2 deletions
diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp
index d1c47095a2..962cb4c42a 100644
--- a/lib/Basic/SourceManager.cpp
+++ b/lib/Basic/SourceManager.cpp
@@ -41,9 +41,10 @@ unsigned ContentCache::getSizeBytesMapped() const {
/// getSize - Returns the size of the content encapsulated by this ContentCache.
/// This can be the size of the source file or the size of an arbitrary
/// scratch buffer. If the ContentCache encapsulates a source file, that
-/// file is not lazily brought in from disk to satisfy this query.
+/// file is not lazily brought in from disk to satisfy this query unless it
+/// needs to be truncated due to a truncateAt() call.
unsigned ContentCache::getSize() const {
- return Entry ? Entry->getSize() : Buffer->getBufferSize();
+ return Buffer ? Buffer->getBufferSize() : Entry->getSize();
}
const llvm::MemoryBuffer *ContentCache::getBuffer() const {
@@ -52,10 +53,54 @@ const llvm::MemoryBuffer *ContentCache::getBuffer() const {
// FIXME: Should we support a way to not have to do this check over
// and over if we cannot open the file?
Buffer = MemoryBuffer::getFile(Entry->getName(), 0, Entry->getSize());
+ if (isTruncated())
+ const_cast<ContentCache *>(this)->truncateAt(TruncateAtLine,
+ TruncateAtColumn);
}
return Buffer;
}
+void ContentCache::truncateAt(unsigned Line, unsigned Column) {
+ TruncateAtLine = Line;
+ TruncateAtColumn = Column;
+
+ if (!isTruncated() || !Buffer)
+ return;
+
+ // Find the byte position of the truncation point.
+ const char *Position = Buffer->getBufferStart();
+ for (unsigned Line = 1; Line < TruncateAtLine; ++Line) {
+ for (; *Position; ++Position) {
+ if (*Position != '\r' && *Position != '\n')
+ continue;
+
+ // Eat \r\n or \n\r as a single line.
+ if ((Position[1] == '\r' || Position[1] == '\n') &&
+ Position[0] != Position[1])
+ ++Position;
+ ++Position;
+ break;
+ }
+ }
+
+ for (unsigned Column = 1; Column < TruncateAtColumn; ++Column, ++Position) {
+ if (!*Position)
+ break;
+
+ if (*Position == '\t')
+ Column += 7;
+ }
+
+ // Truncate the buffer.
+ if (Position != Buffer->getBufferEnd()) {
+ MemoryBuffer *TruncatedBuffer
+ = MemoryBuffer::getMemBufferCopy(Buffer->getBufferStart(), Position,
+ Buffer->getBufferIdentifier());
+ delete Buffer;
+ Buffer = TruncatedBuffer;
+ }
+}
+
unsigned LineTableInfo::getLineTableFilenameID(const char *Ptr, unsigned Len) {
// Look up the filename in the string table, returning the pre-existing value
// if it exists.
@@ -287,6 +332,16 @@ SourceManager::getOrCreateContentCache(const FileEntry *FileEnt) {
EntryAlign = std::max(8U, EntryAlign);
Entry = ContentCacheAlloc.Allocate<ContentCache>(1, EntryAlign);
new (Entry) ContentCache(FileEnt);
+
+ if (FileEnt == TruncateFile) {
+ // If we had queued up a file truncation request, perform the truncation
+ // now.
+ Entry->truncateAt(TruncateAtLine, TruncateAtColumn);
+ TruncateFile = 0;
+ TruncateAtLine = 0;
+ TruncateAtColumn = 0;
+ }
+
return Entry;
}
@@ -1058,6 +1113,28 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
}
}
+void SourceManager::truncateFileAt(const FileEntry *Entry, unsigned Line,
+ unsigned Column) {
+ llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>::iterator FI
+ = FileInfos.find(Entry);
+ if (FI != FileInfos.end()) {
+ FI->second->truncateAt(Line, Column);
+ return;
+ }
+
+ // We cannot perform the truncation until we actually see the file, so
+ // save the truncation information.
+ assert(TruncateFile == 0 && "Can't queue up multiple file truncations!");
+ TruncateFile = Entry;
+ TruncateAtLine = Line;
+ TruncateAtColumn = Column;
+}
+
+/// \brief Determine whether this file was truncated.
+bool SourceManager::isTruncatedFile(FileID FID) const {
+ return getSLocEntry(FID).getFile().getContentCache()->isTruncated();
+}
+
/// PrintStats - Print statistics to stderr.
///
void SourceManager::PrintStats() const {