diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-09-22 21:11:38 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-09-22 21:11:38 +0000 |
commit | b657f115c3b4e262e72906a28cbcf3eaccd9460c (patch) | |
tree | 95502c386d41a13dd1c04b189247446b9fb8d18e /lib/Basic/SourceManager.cpp | |
parent | add28829c7a8d3c5da9ae140f18d3c9ad2d8b599 (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.cpp | 81 |
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 { |