From b657f115c3b4e262e72906a28cbcf3eaccd9460c Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 22 Sep 2009 21:11:38 +0000 Subject: 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 --- lib/Basic/SourceManager.cpp | 81 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 79 insertions(+), 2 deletions(-) (limited to 'lib/Basic/SourceManager.cpp') 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(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(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::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 { -- cgit v1.2.3-18-g5258